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