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 
83 #include "GeoModelKernel/GeoUnidentifiedShape.h"
84 
85 
86 LArGeo::EMECConstruction::EMECConstruction(bool is_tb, bool has_inner, bool has_outer)
87  : AthMessaging("EMECConstruction")
88  , m_fullGeo(true)
89  , m_isTB(is_tb)
90  , m_hasInnerWheel(has_inner)
91  , m_hasOuterWheel(has_outer)
92  , m_innerWheelVariant("Wheel")
93  , m_outerWheelVariant("Wheel") // "Wheel" (Meaning polycone) or "Cone" or "Slices"
94 {
95 }
96 
98 = default;
99 
100 GeoIntrusivePtr<GeoFullPhysVol> LArGeo::EMECConstruction::GetEnvelope(bool bPos)
101 {
102  ISvcLocator *svcLocator = Gaudi::svcLocator();
103  SmartIF<StoreGateSvc> detStore{svcLocator->service("DetectorStore")};
104  if(!detStore.isValid()) {
105  throw std::runtime_error("Error in EndcapCryostatConstruction, cannot access DetectorStore");
106  }
107 
108  // Get GeoModelSvc and RDBAccessSvc
109  SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service("RDBAccessSvc")};
110  if(!pAccessSvc.isValid()) {
111  throw std::runtime_error("EMECConstruction: cannot locate RDBAccessSvc!");
112  }
113 
114  SmartIF<IGeoModelSvc> geoModelSvc{svcLocator->service("GeoModelSvc")};
115  if(!geoModelSvc.isValid()) {
116  throw std::runtime_error("EMECConstruction: cannot locate GeoModelSvc!");
117  }
118 
119  DecodeVersionKey larVersionKey(geoModelSvc, "LAr");
120 
121  // Flag for building detailed absorber. Default=false
122  int multilayered_absorbers = 0;
123  IRDBRecordset_ptr larSwitches = pAccessSvc->getRecordsetPtr("LArSwitches", larVersionKey.tag(), larVersionKey.node());
124  if(larSwitches->size()!=0){
125  if(!(*larSwitches)[0]->isFieldNull("DETAILED_ABSORBER_EC")){
126  multilayered_absorbers = (*larSwitches)[0]->getInt("DETAILED_ABSORBER_EC");
127  } else if(!(*larSwitches)[0]->isFieldNull("DETAILED_ABSORBER")){
128  multilayered_absorbers = (*larSwitches)[0]->getInt("DETAILED_ABSORBER");
129  }
130  }
131 
132  if(multilayered_absorbers > 0){
133  ATH_MSG_INFO( "multi-layered version of absorbers activated, "
134  << "parameter value is " << multilayered_absorbers );
135  }
136 
137  StoredMaterialManager* materialManager = nullptr;
138  if(StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) return nullptr;
139 
141  // Get materials from the manager
143 
144  const GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon");
145  if(!LAr) throw std::runtime_error("Error in EMECConstruction, std::LiquidArgon is not found.");
146 
147  const GeoMaterial* innerAbsorberMaterial = nullptr;
148  std::string innerAbsorberMaterial_name = "LAr::EMEC_Thickabs";
149  if(multilayered_absorbers > 0){
150  if(multilayered_absorbers != 2){
151 // to be replaced with steel - finished by Adam Agocs
152  innerAbsorberMaterial_name = "std::Iron";
153  } else {
154  innerAbsorberMaterial_name = "LAr::EMEC_shell";
155  }
156  }
157  innerAbsorberMaterial = materialManager->getMaterial(innerAbsorberMaterial_name);
158  if(!innerAbsorberMaterial){
159  throw std::runtime_error(
160  (innerAbsorberMaterial_name +
161  " is not found for inner absorber in EMECConstruction.").c_str()
162  );
163  }
164 
165  const GeoMaterial* outerAbsorberMaterial = nullptr;
166  std::string outerAbsorberMaterial_name = "LAr::EMEC_Thinabs";
167  if(multilayered_absorbers > 0){
168  if(multilayered_absorbers != 2){
169 // to be replaced with steel - finished by Adam Agocs
170  outerAbsorberMaterial_name = "std::Iron";
171  } else {
172  outerAbsorberMaterial_name = "LAr::EMEC_shell";
173  }
174  }
175  outerAbsorberMaterial = materialManager->getMaterial(outerAbsorberMaterial_name);
176  if(!outerAbsorberMaterial){
177  throw std::runtime_error(
178  (outerAbsorberMaterial_name +
179  " is not found for outer absorber in EMECConstruction.").c_str()
180  );
181  }
182 
183  const GeoMaterial *Glue = nullptr;
184  const GeoMaterial *Lead = nullptr;
185  if(multilayered_absorbers > 0){
186 // to be replaced with glue and lead - finished by Adam Agocs
187  Glue = materialManager->getMaterial("LAr::Glue");
188  if(!Glue) throw std::runtime_error("Error in EMECConstruction, LAr::Glue is not found.");
189  Lead = materialManager->getMaterial("std::Lead");
190  if(!Lead) throw std::runtime_error("Error in EMECConstruction, LAr::Lead is not found.");
191  }
192 
193  const GeoMaterial* electrodeMaterial = materialManager->getMaterial("LAr::KaptonC");
194  if(!electrodeMaterial) throw std::runtime_error("Error in EMECConstruction, LAr::KaptonC is not found.");
195 
197  // Define geometry
199 
200  // Set up strings for volume names.
201  std::string baseName = "LAr::EMEC";
202 
203  double phiPosition, phiSize;
204 
205  if(m_isTB) {
207  phiSize = M_PI*Gaudi::Units::rad / 8. + 0.065*Gaudi::Units::rad; // half-angle of inner part of module
208  }
209  else {
210  phiPosition = M_PI*Gaudi::Units::rad;
211  phiSize = M_PI*Gaudi::Units::rad; // half-angle of a full wheel
212  }
213 
214  // Define the mother volume for the emec. Everything
215  // else in the emec (wheels,structure, etc.) should be
216  // placed inside here.
217 
218  //double emecMotherZplan[] = {3641.*Gaudi::Units::mm,4273.*Gaudi::Units::mm}; //warm
219 
220  // 21-Jul-2005, C.S. : above line valid in warm, below is in cold.
221  // The latter one should apply, othervise SupportMotherVolumes cross
222  // the EMEC Mother and/or their position rel to the sensitive LAr
223  // become wrong
224 
225 
226  IRDBRecordset_ptr cryoPcons =
227  pAccessSvc->getRecordsetPtr("CryoPcons", larVersionKey.tag(), larVersionKey.node());
228  if(cryoPcons->size() == 0){
229  cryoPcons = pAccessSvc->getRecordsetPtr("CryoPcons", "CryoPcons-EMEC-00");
230  }
231 
232  //double emecMotherZplan[] = {3639.5*Gaudi::Units::mm,3639.5*Gaudi::Units::mm+630.*Gaudi::Units::mm}; //cold (J.T)
233  // // Zplane[0]=endg_z0*Gaudi::Units::cm-50*Gaudi::Units::mm
234  // // Zplane[1]=Zplane[0]+endg_dzende*Gaudi::Units::cm-2.Gaudi::Units::mm
235  //double emecMotherRin[] = { 279.*Gaudi::Units::mm, 324*Gaudi::Units::mm}; //{ 302.*Gaudi::Units::mm, 302.*Gaudi::Units::mm };
236  //double emecMotherRout[] = {(2077.-7)*Gaudi::Units::mm,(2077.-7)*Gaudi::Units::mm}; // -7 for cold
237  //int lastPlaneEmec = (sizeof(emecMotherZplan) / sizeof(double));
238 
239  std::string emecMotherName = baseName + "::Mother"; //+ extension;
240 
241  GeoTransform *refSystemTransform = nullptr;
242  double zTrans = 0.*Gaudi::Units::mm;
243  double zMSTrans = 0.*Gaudi::Units::mm;
244 
245  GeoPcon* emecMotherShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize); //start phi,total phi
246  for(const IRDBRecord_ptr& currentRecord : *cryoPcons) {
247  if(currentRecord->getString("PCON") == "EMEC::Mother"){
248  if(!refSystemTransform){
249  if(m_isTB){
250  zTrans = -3700.5*Gaudi::Units::mm;
251  zMSTrans = zTrans;
252  } else {
253  zTrans = currentRecord->getDouble("ZPLANE") - 3639.5*Gaudi::Units::mm;
254  zMSTrans = 0.*Gaudi::Units::mm;
255  }
256  refSystemTransform = new GeoTransform(GeoTrf::TranslateZ3D(zTrans));
257  }
258  emecMotherShape->addPlane(currentRecord->getDouble("ZPLANE") + zMSTrans,
259  currentRecord->getDouble("RMIN"),
260  currentRecord->getDouble("RMAX"));
261  }
262  }
263 
264  IRDBRecordset_ptr DB_EmecGeometry =
265  pAccessSvc->getRecordsetPtr("EmecGeometry", larVersionKey.tag(), larVersionKey.node());
266  if(DB_EmecGeometry->size() == 0){
267  DB_EmecGeometry = pAccessSvc->getRecordsetPtr("EmecGeometry", "EmecGeometry-00");
268  }
269  double zWheelRefPoint = (*DB_EmecGeometry)[0]->getDouble("Z0")*Gaudi::Units::cm;
270  double dMechFocaltoWRP=(*DB_EmecGeometry)[0]->getDouble("Z1")*Gaudi::Units::cm;
271  double LArTotalThickness = (*DB_EmecGeometry)[0]->getDouble("ETOT") *Gaudi::Units::cm;
272  double halfGapBetweenWheels = (*DB_EmecGeometry)[0]->getDouble("DCRACK")*Gaudi::Units::cm;
273  double rOuterCutoff = (*DB_EmecGeometry)[0]->getDouble("RLIMIT")*Gaudi::Units::cm;
274 
275  IRDBRecordset_ptr DB_EMECmn =
276  pAccessSvc->getRecordsetPtr("EmecMagicNumbers", larVersionKey.tag(), larVersionKey.node());
277  if(DB_EMECmn->size() == 0)
278  DB_EMECmn = pAccessSvc->getRecordsetPtr("EmecMagicNumbers","EMECMagicNumbers-00");
279  double reftoactive = (*DB_EMECmn)[0]->getDouble("REFTOACTIVE") *Gaudi::Units::mm;
280  double activelength = (*DB_EMECmn)[0]->getDouble("ACTIVELENGTH") *Gaudi::Units::mm;
281  double straightstartsection = (*DB_EMECmn)[0]->getDouble("STRAIGHTSTARTSECTION")*Gaudi::Units::mm;
282  double wheelThickness=activelength+2*straightstartsection;
283  double dWRPtoFrontFace = reftoactive;
284  double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace;
285  double zWheelBackFace = zWheelFrontFace+wheelThickness;
286  IRDBRecordset_ptr DB_EMECwp=
287  pAccessSvc->getRecordsetPtr("EmecWheelParameters", larVersionKey.tag(),larVersionKey.node());
288  if (DB_EMECwp->size()==0)
289  DB_EMECwp=pAccessSvc->getRecordsetPtr("EmecWheelParameters", "EmecWheelParameters","EmecWheelParameters-00");
290  int numberOfHalfWavesInner=2*(*DB_EMECwp)[0]->getInt("NACC")+2;
291  int numberOfHalfWavesOuter=2*(*DB_EMECwp)[1]->getInt("NACC")+3;// one extra for outer wheel
292  double eta_hi = (*DB_EMECwp)[0]->getDouble("ETAINT");
293  double eta_mid = (*DB_EMECwp)[0]->getDouble("ETAEXT");
294  double eta_low = (*DB_EMECwp)[1]->getDouble("ETAEXT");
295 
296  // NEW BLURB
297  double zMid[2];
298  double rMin[2][3];
299  double rMax[2][3];
300  {
301  double tanThetaMid = 2. * std::exp(-eta_mid) / (1. - std::exp(-2.*eta_mid));
302  double tanThetaOuter = 2. * std::exp(-eta_low) / (1. - std::exp(-2.*eta_low));
303  double tanThetaInner = 2. * std::exp(-eta_hi ) / (1. - std::exp(-2.*eta_hi ));
304  double inv_tanThetaOuter = (1. - std::exp(-2.*eta_low)) / (2. * std::exp(-eta_low));
305 
306  // Inner Wheel Outer Radius
307  rMax[0][0] = zWheelFrontFace * tanThetaMid - halfGapBetweenWheels;
308  rMax[0][1] = zWheelBackFace * tanThetaMid - halfGapBetweenWheels;
309  // Outer Wheel Outer Radius
310  rMax[1][0] = zWheelFrontFace * tanThetaOuter;
311  rMax[1][1] = rOuterCutoff;
312  rMax[1][2] = rOuterCutoff;
313 
314  // Note that there is a 3mm gap between the outer surface of the
315  // inner wheel and the inner surface of the outer wheel.
316 
317  // Inner Wheel Inner Radius
318  rMin[0][0] = zWheelFrontFace * tanThetaInner;
319  rMin[0][1] = zWheelBackFace * tanThetaInner;
320  zMid[0] = 0;
321 
322  // Outer Wheel Inner Radius
323  rMin[1][0] = zWheelFrontFace * tanThetaMid + halfGapBetweenWheels;
324  rMin[1][1] = rOuterCutoff * inv_tanThetaOuter * tanThetaMid + halfGapBetweenWheels;
325  rMin[1][2] = zWheelBackFace * tanThetaMid + halfGapBetweenWheels;
326  zMid[1] = rOuterCutoff * inv_tanThetaOuter - zWheelFrontFace;
327  }
328 
329  const GeoLogVol* emecMotherLogical =
330  new GeoLogVol(emecMotherName, emecMotherShape, LAr);
331  GeoIntrusivePtr<GeoFullPhysVol> emecMotherPhysical = new GeoFullPhysVol(emecMotherLogical);
332 
333  if(!m_isTB) baseName += bPos? "::Pos": "::Neg";
334 
335  if(m_hasInnerWheel){
336  std::string innerName = baseName + "::Inner";
337  std::string LArName = innerName + (m_isTB? "Module": "Wheel");
338 
339  std::vector<std::string> absorbers;
340  std::vector<std::string> electrodes;
341 
342  if(m_innerWheelVariant == "Cone"){
343  innerName += "Cone";
344  absorbers.push_back(innerName + "::Absorber");
345  electrodes.push_back(innerName + "::Electrode");
346  } else if(m_innerWheelVariant == "Slices"){
347  innerName += "Slice";
348  uint8_t slice = 0; // To silence Wformat-truncation use datatype with 3-digit range
349  do {
350  char buf[4];
351  snprintf(buf, 4, "%02d", slice);
352 
353  std::string a = innerName + buf + "::Absorber";
354  std::string e = innerName + buf + "::Electrode";
355  absorbers.push_back(a);
356  electrodes.push_back(e);
357  slice ++;
358  } while(
359  numberOfHalfWavesInner > slice
360  && slice < 100 // slice number limited by two digits
361  );
362  if(slice >= 100){
363  ATH_MSG_ERROR( "too many LArWheel slices, something"
364  << " goes wrong in EMECConstruction" );
365  }
366  innerName += "s";
367  } else { // it is a Polycone
368  innerName += (m_isTB? "Module": "Wheel");
369  absorbers.push_back(innerName + "::Absorber");
370  electrodes.push_back(innerName + "::Electrode");
371  }
372  ATH_MSG_INFO( "activating " << innerName );
373  ATH_MSG_DEBUG( absorbers.size() << " absorber, "
374  << electrodes.size() << " electrode shapes created" );
375 
376 
377  double zBack = wheelThickness;
378  GeoPcon* innerShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
379  innerShape->addPlane(0.*Gaudi::Units::mm, rMin[0][0], rMax[0][0]);
380  innerShape->addPlane(zBack , rMin[0][1], rMax[0][1]);
381 
382  GeoLogVol* innerLogical = new GeoLogVol (LArName,innerShape, LAr);
383  GeoIntrusivePtr<GeoFullPhysVol> fullPV = new GeoFullPhysVol(innerLogical);
384 
385  emecMotherPhysical->add(new GeoIdentifierTag(1));
386  emecMotherPhysical->add(refSystemTransform);
387  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
388  emecMotherPhysical->add(fullPV);
389 
390  StoredPhysVol *sPhysVol = new StoredPhysVol(fullPV);
391  StatusCode status=detStore->record(sPhysVol, bPos? "EMEC_INNER_WHEEL_POS": "EMEC_INNER_WHEEL_NEG");
392  if(!status.isSuccess()){
393  throw std::runtime_error(bPos? "Cannot store EMEC_INNER_WHEEL_POS": "Cannot store EMEC_INNER_WHEEL_NEG");
394  }
395 
396  if (geoModelSvc->isEmecStandard()){
397  bool makeSlices;
398  ATH_MSG_INFO( "EMECConstruction build NewInnerWheel with standard Geant4 shapes: G4GenericTrap ");
399  EMECAccordionConstruction emecAccordionConstructor;
400  emecAccordionConstructor.setWheelParameters();
401  emecAccordionConstructor.setInnerWheel(fullPV);
402  emecAccordionConstructor.setMaterial("LiquidArgon", LAr);
403  emecAccordionConstructor.setMaterial("Steel", innerAbsorberMaterial);
404  emecAccordionConstructor.setMaterial("Glue", Glue);
405  emecAccordionConstructor.setMaterial("Lead", Lead);
406  emecAccordionConstructor.setMaterial("Kapton", electrodeMaterial);
407  emecAccordionConstructor.constructInnerWheelStructure(makeSlices = true);
408  }
409  else {
410  place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,innerAbsorberMaterial, electrodeMaterial, Glue, Lead);
411  }
412  } // if(m_hasInnerWheel)
413 
414  if(m_hasOuterWheel){
415  std::string outerName = baseName + "::Outer";
416  const std::string LArName = outerName + (m_isTB? "Module": "Wheel");
417 
418  std::vector<std::string> absorbers;
419  std::vector<std::string> electrodes;
420 
421  if(m_outerWheelVariant == "Cone"){
422  absorbers.push_back(outerName + "FrontCone::Absorber");
423  absorbers.push_back(outerName + "BackCone::Absorber");
424  electrodes.push_back(outerName + "FrontCone::Electrode");
425  electrodes.push_back(outerName + "BackCone::Electrode");
426  outerName += "Cones";
427  } else if(m_outerWheelVariant == "Slices"){
428  outerName += "Slice";
429  uint8_t slice = 0; // To silence Wformat-truncation use datatype with 3-digit range
430  do {
431  char buf[4];
432  snprintf(buf, 4, "%02d", slice);
433  std::string a = outerName + buf + "::Absorber";
434  std::string e = outerName + buf + "::Electrode";
435  absorbers.push_back(a);
436  electrodes.push_back(e);
437  slice ++;
438  } while( // outer wheel has an extra slice
439  numberOfHalfWavesOuter > slice
440  && slice < 100 // slice number limited by two digits
441  );
442  if(slice >= 100){
443  ATH_MSG_ERROR( "too many LArWheel slices, something"
444  << " goes wrong in EMECConstruction" );
445  }
446  outerName += "s";
447  } else { // it is Polycone
448  outerName += (m_isTB? "Module": "Wheel");
449  absorbers.push_back(outerName + "::Absorber");
450  electrodes.push_back(outerName + "::Electrode");
451  }
452  ATH_MSG_INFO( "activating " << outerName );
453  ATH_MSG_DEBUG( absorbers.size() << " absorber, "
454  << electrodes.size() << " electrode shapes created" );
455 
456  double zBack = wheelThickness;
457  GeoPcon *outerShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
458  outerShape->addPlane(0.*Gaudi::Units::mm, rMin[1][0], rMax[1][0]);
459  outerShape->addPlane(zMid[1] , rMin[1][1], rMax[1][1]);
460  outerShape->addPlane(zBack , rMin[1][2], rMax[1][2]);
461 
462  GeoLogVol *outerLogical = new GeoLogVol(LArName, outerShape, LAr);
463  GeoIntrusivePtr<GeoFullPhysVol>fullPV = new GeoFullPhysVol(outerLogical);
464 
465  emecMotherPhysical->add(new GeoIdentifierTag(1));
466  emecMotherPhysical->add(refSystemTransform);
467  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
468  emecMotherPhysical->add(fullPV);
469 
470  StoredPhysVol *sPhysVol = new StoredPhysVol(fullPV);
471  StatusCode status = detStore->record(sPhysVol, bPos? "EMEC_OUTER_WHEEL_POS": "EMEC_OUTER_WHEEL_NEG");
472  if(!status.isSuccess()){
473  throw std::runtime_error(bPos? "Cannot store EMEC_OUTER_WHEEL_POS": "Cannot store EMEC_OUTER_WHEEL_NEG");
474  }
475  if (geoModelSvc->isEmecStandard()){
476  bool makeSlices;
477  ATH_MSG_INFO( "EMECConstruction build NewOuterWheel with standard Geant4 shapes: G4GenericTrap ");
478  EMECAccordionConstruction emecAccordionConstructor;
479  emecAccordionConstructor.setWheelParameters();
480  emecAccordionConstructor.setOuterWheel(fullPV);
481  emecAccordionConstructor.setMaterial("LiquidArgon", LAr);
482  emecAccordionConstructor.setMaterial("Steel", outerAbsorberMaterial);
483  emecAccordionConstructor.setMaterial("Glue", Glue);
484  emecAccordionConstructor.setMaterial("Lead", Lead);
485  emecAccordionConstructor.setMaterial("Kapton", electrodeMaterial);
486  emecAccordionConstructor.constructOuterWheelStructure(makeSlices = true);
487 
488  } else {
489  place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,
490  outerAbsorberMaterial, electrodeMaterial, Glue, Lead
491  );
492  }
493 
494  } // if(m_hasOuterWheel)
495 
496 // ***********************************
497 //Description of nonsensitive pieces:*
498 // ***********************************
499 
500  if(m_fullGeo) {
501  double z0;
502 
503  // Volumes for FRONT and BACK support structures
505  FrontSupp = EMECSupportConstruction::Front,
507  if(m_hasInnerWheel && !m_hasOuterWheel){
510  } else if(m_hasOuterWheel && !m_hasInnerWheel){
513  }
514 
515  IRDBRecordset_ptr DMpcons =
516  pAccessSvc->getRecordsetPtr("EmecDMPCons", larVersionKey.tag(), larVersionKey.node());
517  if(DMpcons->size() == 0){
518  DMpcons = pAccessSvc->getRecordsetPtr("EmecDMPCons", "EmecDMPCons-00");
519  }
520 
521  double front_shift = 0.*Gaudi::Units::mm;
522  double back_shift = 0.*Gaudi::Units::mm;
523  try {
524  for(const IRDBRecord_ptr& dmPcon : *DMpcons) {
525  const std::string& object = dmPcon->getString("PCONNAME");
526  if(object == "FrontSupportMother"){
527  int zplane = dmPcon->getInt("NZPLANE");
528  if(zplane == 0) front_shift += dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
529  else if(zplane == 1) front_shift -= dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
530  else continue;
531  } else if(object == "BackSupportMother"){
532  int zplane = dmPcon->getInt("NZPLANE");
533  if(zplane == 0) back_shift -= 0.;//dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
534  else if(zplane == 1) back_shift += dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
535  else continue;
536  }
537  }
538  front_shift += reftoactive;
539  back_shift += LArTotalThickness - reftoactive;
540  }
541  catch (...){
542  front_shift = -50.*Gaudi::Units::mm; // start of EMEC envelop in the cryo.(length of env=630.)
543  back_shift = 580.*Gaudi::Units::mm;
544  std::cout << "EMECConstruction: WARNING: cannot get front|back_shift from DB"
545  << std::endl;
546  }
547 //std::cout << "EMECConstruction : " << front_shift << " " << back_shift << std::endl;
548  z0 = zWheelRefPoint + front_shift;
549  EMECSupportConstruction *fsc = nullptr;
550  if(m_isTB) fsc = new EMECSupportConstruction(FrontSupp, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
551  else fsc = new EMECSupportConstruction(FrontSupp, bPos);
552  GeoIntrusivePtr<GeoPhysVol> physicalFSM = fsc->GetEnvelope();
553  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
554  emecMotherPhysical->add(refSystemTransform);
555  emecMotherPhysical->add(physicalFSM);
556  delete fsc;
557 
558  z0 = zWheelRefPoint + back_shift; // end of EMEC envelop in the cryo.
559  EMECSupportConstruction *bsc = nullptr;
560  if(m_isTB) bsc = new EMECSupportConstruction(BackSupp, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
561  else bsc = new EMECSupportConstruction(BackSupp, bPos);
562  GeoIntrusivePtr<GeoPhysVol>physicalBSM = bsc->GetEnvelope();
563  GeoTrf::Transform3D rotBSM(GeoTrf::RotateX3D(-M_PI));
564  if(m_isTB) rotBSM = GeoTrf::RotateZ3D(M_PI)*rotBSM;
565  emecMotherPhysical->add(refSystemTransform);
566  emecMotherPhysical->add(new GeoTransform(GeoTrf::Transform3D(GeoTrf::Translate3D(0., 0., z0)*rotBSM)));
567  emecMotherPhysical->add(physicalBSM);
568  delete bsc;
569 
570  z0 = zWheelRefPoint + LArTotalThickness * 0.5; //dist. to middle of sens vol. along z from WRP
571  EMECSupportConstruction *osc = nullptr;
574  GeoIntrusivePtr<GeoPhysVol>physicalOSM = osc->GetEnvelope();
575  emecMotherPhysical->add(refSystemTransform);
576  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
577  emecMotherPhysical->add(physicalOSM);
578  delete osc;
579 
580  z0 = zWheelRefPoint + LArTotalThickness * 0.5;
581  EMECSupportConstruction *isc = nullptr;
582  if(m_isTB) isc = new EMECSupportConstruction(EMECSupportConstruction::Inner, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
584  GeoIntrusivePtr<GeoPhysVol>physicalISM = isc->GetEnvelope();
585  emecMotherPhysical->add(refSystemTransform);
586  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
587  emecMotherPhysical->add(physicalISM);
588  delete isc;
589 
590  z0 = zWheelRefPoint + LArTotalThickness * 0.5;
591  EMECSupportConstruction *msc = nullptr;
592  if(m_isTB) msc = new EMECSupportConstruction(EMECSupportConstruction::Middle, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
594  GeoIntrusivePtr<GeoPhysVol>physicalMSM = msc->GetEnvelope();
595  emecMotherPhysical->add(refSystemTransform);
596  emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(z0)));
597  emecMotherPhysical->add(physicalMSM);
598  delete msc;
599  }
600 
601  return emecMotherPhysical;
602 }
603 
605 {
606  m_fullGeo = flag;
607 }
608 
609 // Place the custom accordion volumes into the liquid argon
611  GeoIntrusivePtr<GeoFullPhysVol>fullPV,
612  std::vector<std::string> &absorbers,
613  std::vector<std::string> &electrodes,
614  int multilayered_absorbers,
615  const GeoMaterial *Absorber, const GeoMaterial *Electrode,
616  const GeoMaterial *Glue, const GeoMaterial *Lead
617 )
618 {
619 
620  for(const auto& name: absorbers){
621  GeoLogVol* log_volume = new GeoLogVol(name, new GeoUnidentifiedShape("LArCustomShape", name) , Absorber);
622  GeoIntrusivePtr<GeoPhysVol> phys_volume = new GeoPhysVol(log_volume);
623  fullPV->add(new GeoIdentifierTag(1));
624  fullPV->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
625  fullPV->add(phys_volume);
626  if(multilayered_absorbers > 0){
627  GeoIntrusivePtr<GeoPhysVol> glue_phys = phys_volume;
628  std::string lead_name = name;
629  size_t repl = lead_name.find("Absorber");
630  if(std::string::npos != repl) lead_name.replace(repl, 8, "Lead");
631  else throw std::runtime_error(lead_name + ": cannot find 'Absorber'");
632  if(multilayered_absorbers != 2){
633  std::string glue_name = name;
634  glue_name.replace(repl, 8, "Glue");
635  GeoLogVol* glue_log = new GeoLogVol(glue_name, new GeoUnidentifiedShape("LArCustomShape",glue_name), Glue);
636  glue_phys = new GeoPhysVol(glue_log);
637  phys_volume->add(new GeoIdentifierTag(1));
638  phys_volume->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
639  phys_volume->add(glue_phys);
640  }
641  GeoLogVol *lead_log = new GeoLogVol(lead_name, new GeoUnidentifiedShape("LArCustomShape",lead_name), Lead);
642  GeoIntrusivePtr<GeoPhysVol>lead_phys = new GeoPhysVol(lead_log);
643  glue_phys->add(new GeoIdentifierTag(1));
644  glue_phys->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
645  glue_phys->add(lead_phys);
646  }
647  }
648 
649  for(const auto& name: electrodes){
650  GeoLogVol* log_volume = new GeoLogVol(name, new GeoUnidentifiedShape("LArCustomShape",name), Electrode);
651  GeoIntrusivePtr<GeoPhysVol> phys_volume = new GeoPhysVol(log_volume);
652  fullPV->add(new GeoIdentifierTag(1));
653  fullPV->add(new GeoTransform(GeoTrf::Transform3D::Identity()));
654  fullPV->add(phys_volume);
655  }
656 }
EMECSupportConstruction.h
Declaration of EMECSupportConstruction class.
LArGeo::EMECSupportConstruction::FrontOuter
@ FrontOuter
Definition: EMECSupportConstruction.h:54
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
LArGeo::EMECAccordionConstruction::setOuterWheel
void setOuterWheel(GeoFullPhysVol *outerWheel)
Definition: EMECAccordionConstruction.cxx:218
LArGeo::EMECSupportConstruction::GetEnvelope
virtual GeoIntrusivePtr< GeoPhysVol > GetEnvelope(void) const
Definition: EMECSupportConstruction.cxx:269
EMECAccordionConstruction.h
Declaration of EMECAccordionConstruction class.
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:557
LAr
Definition: LArVolumeBuilder.h:36
LArGeo::EMECSupportConstruction::type_t
type_t
Definition: EMECSupportConstruction.h:51
LArGeo::EMECAccordionConstruction::constructOuterWheelStructure
void constructOuterWheelStructure(bool makeSlices=true)
Definition: EMECAccordionConstruction.cxx:1258
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:97
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
LArGeo::EMECSupportConstruction::Middle
@ Middle
Definition: EMECSupportConstruction.h:52
LArGeo::EMECSupportConstruction::Outer
@ Outer
Definition: EMECSupportConstruction.h:52
StoredPhysVol
Definition: StoredPhysVol.h:27
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
LArGeo::EMECAccordionConstruction
Class for construction of EMEC internal structure.
Definition: EMECAccordionConstruction.h:36
LArGeo::EMECSupportConstruction::Front
@ Front
Definition: EMECSupportConstruction.h:52
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:49
perfmonmt-refit.slice
slice
Definition: perfmonmt-refit.py:52
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:53
LArGeo::EMECAccordionConstruction::setInnerWheel
void setInnerWheel(GeoFullPhysVol *innerWheel)
Definition: EMECAccordionConstruction.cxx:192
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:100
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:604
DecodeVersionKey::tag
const std::string & tag() const
Return version tag.
Definition: DecodeVersionKey.cxx:91
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:52
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
LArGeo::EMECAccordionConstruction::setMaterial
void setMaterial(const std::string &name, const GeoMaterial *material)
Definition: EMECAccordionConstruction.cxx:313
LArGeo::EMECSupportConstruction::Inner
@ Inner
Definition: EMECSupportConstruction.h:52
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
StoredMaterialManager.h
DecodeVersionKey.h
LArGeo::EMECConstruction::EMECConstruction
EMECConstruction(bool is_tb=false, bool has_inner=true, bool has_outer=true)
Definition: EMECConstruction.cxx:86
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
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:54
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
LArGeo::EMECAccordionConstruction::constructInnerWheelStructure
void constructInnerWheelStructure(bool makeSlices=true)
Definition: EMECAccordionConstruction.cxx:1184
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:610
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
python.PhysicalConstants.halfpi
float halfpi
Definition: PhysicalConstants.py:51
LArGeo::EMECSupportConstruction::FrontInner
@ FrontInner
Definition: EMECSupportConstruction.h:53
IGeoModelSvc.h
StoreGateSvc.h
EMECConstruction.h
Declaration of EMECConstruction class.
LArGeo::EMECAccordionConstruction::setWheelParameters
void setWheelParameters()
Definition: EMECAccordionConstruction.cxx:51
python.SystemOfUnits.rad
int rad
Definition: SystemOfUnits.py:111
StoredPhysVol.h