ATLAS Offline Software
Loading...
Searching...
No Matches
HECWheelConstruction.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// HECWheelConstruction.cxx 1.0.0
6//
7// This provides a mother volume for the ATLAS Front HEC or Rear HEC,
8// gets the modules from the HECModuleConstruction and arranges
9// them into a FrontWheel or RearWheel respectively.
10// The LAr gaps can be equipped with either one thick PAD+EST board
11// or with 3 individual boards (1 PAD + 2 EST).
12//
13// M. Fincke-Keeler
14//
15//====================================================================
19
20#include "GeoModelKernel/GeoElement.h"
21#include "GeoModelKernel/GeoMaterial.h"
22#include "GeoModelKernel/GeoFullPhysVol.h"
23#include "GeoModelKernel/GeoPhysVol.h"
24#include "GeoModelKernel/GeoVPhysVol.h"
25#include "GeoModelKernel/GeoLogVol.h"
26#include "GeoModelKernel/GeoPcon.h"
27#include "GeoModelKernel/GeoTubs.h"
28#include "GeoModelKernel/GeoNameTag.h"
29#include "GeoModelKernel/GeoTransform.h"
30#include "GeoModelKernel/GeoAlignableTransform.h"
31#include "GeoModelKernel/GeoIdentifierTag.h"
32#include "GeoModelKernel/GeoSerialTransformer.h"
33#include "GeoModelKernel/GeoSerialIdentifier.h"
34#include "GeoModelKernel/GeoXF.h"
35#include "GeoModelKernel/GeoDefinitions.h"
36#include "GeoGenericFunctions/Variable.h"
39#include "GaudiKernel/MsgStream.h"
40#include "GaudiKernel/Bootstrap.h"
41#include "GaudiKernel/SystemOfUnits.h"
43
44
49
50#include <string>
51#include <cmath>
52#include <iostream>
53
54
55using Gaudi::Units::cm;
56using Gaudi::Units::mm;
57using Gaudi::Units::deg;
58using GeoTrf::RotateZ3D;
59
60
61//Constructor
62LArGeo::HECWheelConstruction::HECWheelConstruction(bool fullGeo, const std::string& wheelType, bool threeBoards, bool posZSide):
63 m_posZSide(posZSide),
64 m_threeBoards(threeBoards),
65 m_wheelType(wheelType),
66 m_fullGeo(fullGeo)
67{
68 m_frontWheel = m_wheelType=="front";
69}
70
71//~Destructor
73
74
75GeoIntrusivePtr<GeoFullPhysVol> LArGeo::HECWheelConstruction::GetEnvelope() {
76
77 // Get access to the material manager:
78
79 ISvcLocator *svcLocator = Gaudi::svcLocator();
80
81 MsgStream log(Athena::getMessageSvc(),"HECWheelConstruction " );
82
83 log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endmsg;
84 log << MSG::DEBUG << "+ +" << endmsg;
85 log << MSG::DEBUG << "+ Start of HECWheel GeoModel definition +" << endmsg;
86 log << MSG::DEBUG << "+ +" << endmsg;
87 log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endmsg;
88
89
90 SmartIF<StoreGateSvc> detStore{svcLocator->service("DetectorStore")};
91 if(!detStore.isValid()) {
92 throw std::runtime_error("Error in HECWheelConstruction, cannot access DetectorStore");
93 }
94
95
96 StoredMaterialManager* materialManager = nullptr;
97 if (StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) {
98 throw std::runtime_error("Error in HECWheelConstruction, cannot access Material Manager");
99 }
100
101 const GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon");
102 if (!LAr) throw std::runtime_error("Error in HECWheelConstruction, std::LiquidArgon is not found.");
103
104 const GeoMaterial *Iron = materialManager->getMaterial("std::Iron");
105 if (!Iron) throw std::runtime_error("Error in HECWheelConstruction, std::Iron is not found.");
106
107
108
109 StatusCode sc;
110 SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service("RDBAccessSvc")};
111 if(!pAccessSvc.isValid()) {
112 throw std::runtime_error ("Cannot locate RDBAccessSvc!!");
113 }
114
115 SmartIF<IGeoModelSvc> geoModel{svcLocator->service ("GeoModelSvc")};
116 if(!geoModel.isValid()) {
117 throw std::runtime_error ("Cannot locate GeoModelSvc!!");
118 }
119
120 std::string AtlasVersion = geoModel->atlasVersion();
121 std::string LArVersion = geoModel->LAr_VersionOverride();
122
123 std::string detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion;
124 std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr";
125
126 IRDBRecordset_ptr hadronicEndcap = pAccessSvc->getRecordsetPtr("HadronicEndcap",detectorKey, detectorNode);
127 if(hadronicEndcap->size()>0)
128 log << MSG::DEBUG << "Using numbers from HadronicEndcap tag: " << hadronicEndcap->tagName() << endmsg;
129 else
130 throw std::runtime_error("Error in HECConstruction: hadronicEendcap not found");
131
132 IRDBRecordset_ptr hecLongitudinalBlock = pAccessSvc->getRecordsetPtr("HecLongitudinalBlock",detectorKey, detectorNode);
133 if(hecLongitudinalBlock->size()>0)
134 log << MSG::DEBUG << "Using numbers from HecLongitudinalBlock tag: " << hecLongitudinalBlock->tagName() << endmsg;
135 else
136 throw std::runtime_error("Error in HECConstruction: hecLongitudinalBlock not found");
137
138 IRDBRecordset_ptr coldContraction = pAccessSvc->getRecordsetPtr("ColdContraction",detectorKey, detectorNode);
139 if(coldContraction->size()>0)
140 log << MSG::DEBUG << "Numbers from ColdContraction db (not used yet) tag: " << coldContraction->tagName() << endmsg;
141 else
142 throw std::runtime_error("Error in HECConstruction: ColdContraction not found");
143
144 //----------------------------------------------------------------
145 // Collect all the numbers we need from the database:
146 //----------------------------------------------------------------
147
148 // This will have to come into action once we are all ready to go cold:
149 // (what's still missing right now are the proper densities to go with it)
150 //double shrinkCold = (*coldContraction)[0]->getDouble("ABSORBERCONTRACTION");
151
152 double shrinkCold = 1.0; // thermal expansion factor: 1.0 = warm geometry
153
154 int moduleNumber = (*hadronicEndcap)[0]->getInt("NSCT");
155 double drModOverlap = shrinkCold * (*hadronicEndcap)[0]->getDouble("DRMODOVERLAP")*cm;
156 double rOuter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm;
157 if (rOuter<2100.*mm) rOuter = shrinkCold * 2130*mm; // Needs fixing in database to make room for HEC Clamping bars!
158 // Caution: We'll need 2 Routers - One for Wheel, one for Module!
159 double rInner1 = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMN")*cm;
160 double rInner2 = shrinkCold * (*hecLongitudinalBlock)[1]->getDouble("BLRMN")*cm;
161 double firstFrontAbsThickness= shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("PLATE0")*cm;
162 double firstRearAbsThickness = shrinkCold * (*hecLongitudinalBlock)[3]->getDouble("PLATE0")*cm;
163 double frontAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_0")*cm;
164 double rearAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_1")*cm;
165 double gapSize = shrinkCold * (*hadronicEndcap)[0]->getDouble("LARG")*cm;
166 int gapNumber[7];
167 for (int id=0; id<7;id++) gapNumber[id] = (int) (*hecLongitudinalBlock)[id]->getDouble("BLMOD");
168
169
170 //---- Calculate the sizes of the 7 longitudinal Depths -------------------------------------
171 double depthSize[7];
172 depthSize[0] = firstFrontAbsThickness + gapNumber[0]*(frontAbsThickness+gapSize);
173 depthSize[1] = gapNumber[1]*(frontAbsThickness+gapSize);
174 depthSize[2] = gapNumber[2]*(frontAbsThickness+gapSize);
175 depthSize[3] = firstRearAbsThickness + gapNumber[3]*(rearAbsThickness+gapSize);
176 depthSize[4] = gapNumber[4]*(rearAbsThickness+gapSize);
177 depthSize[5] = gapNumber[5]*(rearAbsThickness+gapSize);
178 depthSize[6] = gapNumber[6]*(rearAbsThickness+gapSize);
179
180 //--- From the depth Size, calculate the boundary planes of the Wheel Mother volume ---------
181 // (Add 0.2 mm to avoid clashes)
182 double g4allow = shrinkCold * 0.2*mm;
183 double zCoordinate[4];
184 if (m_frontWheel){
185 zCoordinate[0] = shrinkCold * 0.0*cm;
186 zCoordinate[1] = depthSize[0]; //280.5*mm; (end of the section with the long plates)
187 zCoordinate[2] = depthSize[0] + g4allow; //280.6*mm;
188 zCoordinate[3] = depthSize[0] + depthSize[1] + depthSize[2] + g4allow; // End of front Module
189 }
190 else{
191 zCoordinate[0] = shrinkCold * 0.0*cm;
192 zCoordinate[1] = depthSize[3] + depthSize[4] + depthSize[5] + depthSize[6] + g4allow; // End of rear
193 }
194
195 //---- And here we have some (yikes!) hard-coded values: -------------------------------------
196 // The somewhat odd looking phistart arranges that the y-axis lines up
197 // with the (radial) symmetry axis of of the module.
198 // This is important for the calculator.
199 //
200 double modulePhistart = 264.375*deg; // (270.-11.25/2.)*deg
201 double moduleDeltaPhi = 2*M_PI/moduleNumber; //11.25*deg;
202
203 int nZplane = 4;
204 if (!m_frontWheel) nZplane = 2;
205
206
207
208 //----------------------------------------------------------------
209 // HECWheel
210 //----------------------------------------------------------------
211 GeoPcon* solidHECWheel = new GeoPcon(0., 2.*M_PI);
212 for (int i=0; i< nZplane; i++)
213 {
214 double innerRadius = rInner2;
215 if (i<2 && m_frontWheel) innerRadius=rInner1;
216 solidHECWheel->addPlane(zCoordinate[i],innerRadius-drModOverlap,rOuter);
217 }
218 std::string hecFrontName = "LAr::HEC::LiquidArgon";
219 const GeoLogVol* logicHECWheel = new GeoLogVol(hecFrontName, solidHECWheel , LAr);
220 GeoIntrusivePtr<GeoFullPhysVol> physiHECWheel{new GeoFullPhysVol(logicHECWheel)};
221
222
223 if(m_fullGeo) {
224
225 //----------------------------------------------------------------
226 // Get HEC Modules
227 //----------------------------------------------------------------
228 // NB: HECModuleConstruction( threeBoards, frontWheel, TB,TByear) ;
229
231 PVLink moduleEnvelope = HECModule.GetEnvelope();
232
233 //----------------------------------------------------------------
234 // Place Modules into HEC Wheel
235 //----------------------------------------------------------------
236 // Rotation angle is: 11.25/2 + Index * 11.25*deg
237 // Modules are numbered mirror-symmetric in pos/neg z-side!
238
239 GeoSerialIdentifier *sIF = new GeoSerialIdentifier(0);
240 GeoGenfun::Variable Index;
241
242 if (m_posZSide) {
243 GeoGenfun::GENFUNCTION ModuleRotationAngle = -modulePhistart + moduleDeltaPhi*Index;
244 GeoXF::TRANSFUNCTION t = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngle);
245 GeoSerialTransformer *sTF = new GeoSerialTransformer (moduleEnvelope,&t,moduleNumber);
246 physiHECWheel->add(sIF);
247 physiHECWheel->add(sTF);
248 } else {
249 //For the neg z-side have to build everything in the opposite sense from pos-z wheel.
250 GeoGenfun::GENFUNCTION ModuleRotationAngle1 = -modulePhistart+180*deg-moduleDeltaPhi - moduleDeltaPhi*Index;
251 GeoXF::TRANSFUNCTION t1 = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngle1);
252 GeoSerialTransformer *sTF1 = new GeoSerialTransformer (moduleEnvelope,&t1,moduleNumber);
253 physiHECWheel->add(sIF);
254 physiHECWheel->add(sTF1);
255 }
256
257 //----------------------------------------------------------------
258 // Add Outer Connecting Bars to HEC Wheel
259 //----------------------------------------------------------------
260
262 HECClamp.AddClamps(physiHECWheel);
263 }
264
265 return physiHECWheel;
266}
267
#define M_PI
#define endmsg
Declaration of HECModuleConstruction 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.
IndexedConstituentUserInfo::Index Index
static Double_t sc
#define deg
virtual std::string tagName() const =0
virtual unsigned int size() const =0
void AddClamps(GeoIntrusivePtr< GeoFullPhysVol > physiHECWheel)
GeoModel description of LAr HECModule.
GeoIntrusivePtr< GeoFullPhysVol > GetEnvelope()
HECWheelConstruction(bool fullGeo, const std::string &wheelType="front", bool threeBoards=false, bool posZSide=true)
GeoIntrusivePtr< GeoFullPhysVol > GetEnvelope()
This class holds one or more material managers and makes them storeable, under StoreGate.
virtual const GeoMaterial * getMaterial(const std::string &name)=0
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)