ATLAS Offline Software
Loading...
Searching...
No Matches
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"
73#include "GaudiKernel/IService.h"
74#include "GaudiKernel/ISvcLocator.h"
75#include "GaudiKernel/PhysicalConstants.h"
76
80
84#include "GeoModelKernel/GeoUnidentifiedShape.h"
85
86
87LArGeo::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
101GeoIntrusivePtr<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) {
207 phiPosition = Gaudi::Units::halfpi*Gaudi::Units::rad;
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
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;
564 if(m_isTB) osc = new EMECSupportConstruction(EMECSupportConstruction::Outer, bPos, true, "LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
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}
#define M_PI
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Declaration of EMECAccordionConstruction class.
Declaration of EMECConstruction class.
Declaration of EMECSupportConstruction class.
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
const std::string & tag() const
Return version tag.
const std::string & node() const
Return the version node.
virtual unsigned int size() const =0
Class for construction of EMEC internal structure.
void constructInnerWheelStructure(bool makeSlices=true)
void setInnerWheel(GeoFullPhysVol *innerWheel)
void setOuterWheel(GeoFullPhysVol *outerWheel)
void setMaterial(const std::string &name, const GeoMaterial *material)
void constructOuterWheelStructure(bool makeSlices=true)
EMECConstruction(bool is_tb=false, bool has_inner=true, bool has_outer=true)
virtual GeoIntrusivePtr< GeoFullPhysVol > GetEnvelope(bool bPos=true)
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)
GeoModel description of the EMEC Support Structures.
virtual GeoIntrusivePtr< GeoPhysVol > GetEnvelope(void) const
This class holds one or more material managers and makes them storeable, under StoreGate.
virtual const GeoMaterial * getMaterial(const std::string &name)=0