ATLAS Offline Software
Loading...
Searching...
No Matches
LUCID_DetectorFactory.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "GeoModelKernel/GeoMaterial.h"
7#include "GeoModelKernel/GeoElement.h"
8#include "GeoModelKernel/GeoPcon.h"
9#include "GeoModelKernel/GeoTube.h"
10#include "GeoModelKernel/GeoCons.h"
11#include "GeoModelKernel/GeoLogVol.h"
12#include "GeoModelKernel/GeoNameTag.h"
13#include "GeoModelKernel/GeoPhysVol.h"
14#include "GeoModelKernel/GeoFullPhysVol.h"
15#include "GeoModelKernel/GeoTransform.h"
16#include "GeoModelKernel/GeoAlignableTransform.h"
17#include "GeoModelKernel/GeoDefinitions.h"
18#include "GeoModelKernel/Units.h"
24
26#include "GaudiKernel/MsgStream.h"
27#include "GaudiKernel/SystemOfUnits.h"
30
32#include "GetRefIndex.h"
33
34#include "LUCID_RDBAaccess.h"
35
36#include <iomanip>
37
39 IRDBAccessSvc* pAccess)
40 :m_detectorManager(nullptr),
41 m_materialManager(nullptr),
42 m_detectorStore (detStore),
43 m_access (pAccess),
44 m_lp (new LUCID_RDBAccess()) {
45
46 m_quartz = nullptr;
47 m_peek = nullptr;
48}
49
53
54void LUCID_DetectorFactory::create(GeoPhysVol* world) {
55
56 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory::create");
57
58 log << MSG::INFO << " LUCID_DetectorFactory::create " << endmsg;
59
61
62 if (StatusCode::SUCCESS != m_detectorStore->retrieve(m_materialManager, std::string("MATERIALS"))) return;
63
65
66 log << MSG::DEBUG << " Build LUCID side A " << endmsg;
67
68 GeoPcon* aShape = new GeoPcon(0, 360*Gaudi::Units::deg);
69
70 double VJConOuterRadFront = 110;
71 double VJConOuterRadBack = 187;
72 double VJConFrontLength = 225;
73 double VJConMidLength = 4485;
74 double VJConBackLength = 425;
75 double VJConFrontRingInnerRad = 100;
76 double VJConBackRingInerRad = 152;
77
78 aShape->addPlane( 0, VJConFrontRingInnerRad-10, VJConOuterRadFront+10);
79 aShape->addPlane(VJConFrontLength, VJConFrontRingInnerRad-10, VJConOuterRadFront+10);
80 aShape->addPlane(VJConFrontLength+VJConMidLength, VJConFrontRingInnerRad-10, VJConOuterRadBack +10);
81 aShape->addPlane(5036, VJConBackRingInerRad -10, VJConOuterRadBack +10);
82 aShape->addPlane(VJConFrontLength+VJConMidLength+VJConBackLength+30, VJConBackRingInerRad -10, VJConOuterRadBack +10);
83
84 GeoLogVol* logVol = new GeoLogVol("Lucid", aShape, m_materialManager->getMaterial("std::Air"));
85 GeoFullPhysVol* phyVolA = new GeoFullPhysVol(logVol);
86
87 addVJcone (phyVolA);
88 addVJconeFrontRing (phyVolA);
89 addVJconeBackRing (phyVolA);
91 addPmtSupportCylinder (phyVolA);
92 addPmtTubes (phyVolA);
93 addPmtSupport (phyVolA);
94
95 double VJConeDistanceToIP = 13442;
96
97 world->add(new GeoAlignableTransform(GeoTrf::Translate3D(0, 0, VJConeDistanceToIP)));
98 world->add(new GeoNameTag("LucidSideA"));
99 world->add(phyVolA);
100
101 m_detectorManager->addTreeTop(phyVolA);
102
103 log << MSG::DEBUG << " Build LUCID side C " << endmsg;
104
105 GeoFullPhysVol* phyVolC = phyVolA->clone();
106
107 world->add(new GeoAlignableTransform(GeoTrf::Translate3D(0, 0, -VJConeDistanceToIP )*GeoTrf::RotateY3D(180*Gaudi::Units::degree)*GeoTrf::RotateZ3D(180*Gaudi::Units::degree)));
108 world->add(new GeoNameTag("LucidSideC"));
109 world->add(phyVolC);
110
111 m_detectorManager->addTreeTop(phyVolC);
112}
113
115
116 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory::buildMaterials");
117
118 log << MSG::INFO << " LUCID_DetectorFactory::buildMaterials " << endmsg;
119
120 log << MSG::DEBUG << " Wavelength dependent properties " << endmsg;
121
122 const int waveLengthNum = (int)((m_lp->waveLengthMax - m_lp->waveLengthMin)/m_lp->waveLengthStep);
123
124 double* photonWaveLength = new double[waveLengthNum];
125 double* photonEnergy = new double[waveLengthNum];
126 double* quartzRefIndex = new double[waveLengthNum];
127
128 log << MSG::INFO << " Lambda[nm] Energy[eV] QuartzRefIndex " << endmsg;
129
130 for(int i=0; i<waveLengthNum; i++) {
131
132 photonWaveLength[i] = (m_lp->waveLengthMin + i*m_lp->waveLengthStep)*Gaudi::Units::nm;
133 photonEnergy [i] = 2.*M_PI*(Gaudi::Units::hbarc/(Gaudi::Units::eV*Gaudi::Units::nm))/(photonWaveLength[i]/Gaudi::Units::nm)*Gaudi::Units::eV;
134 quartzRefIndex [i] = GetRefIndexQuartz (photonWaveLength[i]/Gaudi::Units::nm);
135 }
136
137 log << MSG::DEBUG << " **************************************************************************************************** " << endmsg;
138 log << MSG::DEBUG << " Lambda[nm] Energy[eV] QuartzRefIndex GasRefIndex GasAbsLength[m] TubeReflectivity " << endmsg;
139
140 for(int i=0; i<waveLengthNum; i++) {
141
142 log << MSG::DEBUG
143 << std::setw(11) << photonWaveLength[i]/Gaudi::Units::nm
144 << std::setw(11) << photonEnergy [i]/Gaudi::Units::eV
145 << std::setw(13) << quartzRefIndex [i]
146 << endmsg;
147 }
148
149 log << MSG::DEBUG << " ********************************************************************************************************** " << endmsg;
150
151 log << MSG::DEBUG << " Build Quartz for PMT windows" << endmsg;
152
153 m_quartz = new GeoExtendedMaterial("SiO2", m_lp->quartzDensity, stateSolid, Gaudi::Units::STP_Temperature);
154
155 const GeoElement* oxygen = m_materialManager->getElement("Oxygen");
156 const GeoElement* silicon = m_materialManager->getElement("Silicon");
157
158 m_quartz->add(const_cast<GeoElement*>(silicon), 1*silicon->getA()/(2*oxygen->getA() + 1*silicon->getA()));
159 m_quartz->add(const_cast<GeoElement*>(oxygen) , 2*oxygen->getA() /(2*oxygen->getA() + 1*silicon->getA()));
160
162
163 mpt->AddProperty("RINDEX", photonEnergy, quartzRefIndex , waveLengthNum);
164
165 log << MSG::DEBUG << "LUCID Quartz Material Properties Table " << mpt << endmsg;
166
167 m_quartz->SetMaterialPropertiesTable(mpt);
168 m_quartz->lock();
169
170 delete [] photonWaveLength;
171 delete [] photonEnergy;
172 delete [] quartzRefIndex;
173
174 log << MSG::DEBUG << " Build Peek: Carbon with density 1.320*g/cm3 " << endmsg;
175
176 m_peek = new GeoMaterial("peek", 1.320*GeoModelKernelUnits::g/Gaudi::Units::cm3);
177 const GeoElement* carbon = m_materialManager->getElement("Carbon");
178 m_peek->add(const_cast<GeoElement*>(carbon),1.0);
179 m_peek->lock();
180}
181
182void LUCID_DetectorFactory::addVJcone(GeoFullPhysVol* parent) {
183
184 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory::addVJcone");
185
186 log << MSG::INFO << " LUCID_DetectorFactory::addVJcone " << endmsg;
187
188 double VJConInerRadFront = 105;
189 double VJConOuterRadFront = 110;
190 double VJConInerRadBack = 182;
191 double VJConOuterRadBack = 187;
192 double VJConFrontLength = 225;
193 double VJConMidLength = 4485;
194 double VJConBackLength = 425;
195
196 GeoPcon* aShape = new GeoPcon(0, 360*Gaudi::Units::degree);
197
198 aShape->addPlane( 0, VJConInerRadFront, VJConOuterRadFront);
199 aShape->addPlane(VJConFrontLength, VJConInerRadFront, VJConOuterRadFront);
200 aShape->addPlane(VJConFrontLength+VJConMidLength, VJConInerRadBack, VJConOuterRadBack);
201 aShape->addPlane(VJConFrontLength+VJConMidLength+VJConBackLength, VJConInerRadBack, VJConOuterRadBack);
202
203 GeoLogVol* logVol = new GeoLogVol("lvVJcone", aShape, m_materialManager->getMaterial("std::Carbon"));
204 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
205
206 parent->add(new GeoTransform(GeoTrf::Translate3D(0, 0, 0)));
207 parent->add(new GeoNameTag("VJcone"));
208 parent->add(phyVol);
209}
210
211void LUCID_DetectorFactory::addVJconeFrontRing(GeoFullPhysVol* parent) {
212
213 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory");
214
215 log << MSG::INFO << " LUCID_DetectorFactory::addVJconeFrontRing " << endmsg;
216
217 double VJConFrontRingLength = 215;
218 double VJConFrontRingInnerRad = 100;
219 double VJConInerRadFront = 105;
220
221 GeoShape* aShape = new GeoTube(VJConFrontRingInnerRad, VJConInerRadFront, VJConFrontRingLength/2);
222 GeoLogVol* logVol = new GeoLogVol("lvVJconeFrontRing", aShape, m_materialManager->getMaterial("std::Aluminium"));
223 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
224
225 parent->add(new GeoTransform(GeoTrf::Translate3D(0, 0, VJConFrontRingLength/2)));
226 parent->add(new GeoNameTag("VJconeFrontRing"));
227 parent->add(phyVol);
228}
229
230void LUCID_DetectorFactory::addVJconeBackRing(GeoFullPhysVol* parent) {
231
232 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory");
233
234 log << MSG::INFO << " LUCID_DetectorFactory::addVJconeBackRing " << endmsg;
235
236 double VJConBackRingLength = 35;
237 double VJConBackRingCentrePosition = (18567-13442)+(VJConBackRingLength/2);
238 double VJConBackRingInerRad = 152;
239 double LucidCylinderRadius = 177;
240
241 GeoShape* aShape = new GeoTube(VJConBackRingInerRad, LucidCylinderRadius, VJConBackRingLength/2);
242 GeoLogVol* logVol = new GeoLogVol("lvVJconeBackRing", aShape, m_materialManager->getMaterial("std::Aluminium"));
243 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
244
245 parent->add(new GeoTransform(GeoTrf::Translate3D(0, 0, VJConBackRingCentrePosition)));
246 parent->add(new GeoNameTag("VJconeBackRing"));
247 parent->add(phyVol);
248}
249
251
252 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory");
253
254 log << MSG::INFO << " LUCID_DetectorFactory::addLucidSupportCylinder " << endmsg;
255
256 double LucidCylinderRadius = 110;
257 double LucidCylinderThickness = 1.5;
258 double LucidCylinderLength = 18400-16850;
259 double LucidCylinderCenterPosition = (16850-13442)+(LucidCylinderLength/2);
260
261 GeoShape* aShape = new GeoTube (LucidCylinderRadius, LucidCylinderRadius + LucidCylinderThickness, LucidCylinderLength/2);
262 GeoLogVol* logVol = new GeoLogVol("lvLucidSupportCylinder", aShape, m_materialManager->getMaterial("std::Carbon"));
263 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
264
265 parent->add(new GeoTransform(GeoTrf::Translate3D(0, 0,LucidCylinderCenterPosition)));
266 parent->add(new GeoNameTag("LucidSupportCylinder"));
267 parent->add(phyVol);
268}
269
271
272 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory");
273
274 log << MSG::INFO << " LUCID_DetectorFactory::addPmtSupportCylinder " << endmsg;
275
276 double PmtSupportCylinderRadius = 111.75;
277 double PmtSupportCylinderThickness = 1.5;
278 double PmtSupportCylinderLength = 17120-16920;
279 double PmtSupportCylinderCenterPosition = (16920-13442)+(PmtSupportCylinderLength/2);
280
281 GeoShape* aShape = new GeoTube (PmtSupportCylinderRadius, PmtSupportCylinderRadius + PmtSupportCylinderThickness, PmtSupportCylinderLength/2);
282 GeoLogVol* logVol = new GeoLogVol("lvPmtSupportCylinder", aShape, m_materialManager->getMaterial("std::Aluminium"));
283 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
284
285 parent->add(new GeoTransform(GeoTrf::Translate3D(0, 0, PmtSupportCylinderCenterPosition)));
286 parent->add(new GeoNameTag("PmtSupportCylinder"));
287 parent->add(phyVol);
288}
289
290void LUCID_DetectorFactory::addPmtSupport(GeoFullPhysVol* parent) {
291
292 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory");
293
294 log << MSG::INFO << " LUCID_DetectorFactory::addPmtSupport" << endmsg;
295
296 double PmtSupportRadius = 113.25;
297 double PmtSupportThickness = 3.4;
298 double PmtSupportLength = 17082-16962;
299 double PmtSupportFrontPosition = (16962-13442);
300
301 int nSections = 4;
302
303 for (int sec=0; sec<nSections; sec++) {
304
305 GeoPcon* aShape = new GeoPcon(0.134 * M_PI +(sec-1)*(M_PI/2),0.232 * M_PI);
306
307 aShape->addPlane( 0, PmtSupportRadius, PmtSupportRadius+PmtSupportThickness);
308 aShape->addPlane(PmtSupportLength, PmtSupportRadius, PmtSupportRadius+PmtSupportThickness);
309
310 GeoLogVol* logVol = new GeoLogVol("lvPmtSupport", aShape, m_materialManager->getMaterial("std::Aluminium"));
311 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
312
313 parent->add(new GeoTransform(GeoTrf::Translate3D(0, 0, PmtSupportFrontPosition)));
314 parent->add(new GeoNameTag("PmtSupport"));
315 parent->add(phyVol);
316 }
317}
318
319void LUCID_DetectorFactory::addPmtTubes(GeoFullPhysVol* parent) {
320
321 MsgStream log(Athena::getMessageSvc(), "LUCID_DetectorFactory");
322
323 log << MSG::INFO << " LUCID_DetectorFactory::addPmtTubes " << endmsg;
324
325 double MUMetalCylinderInnerRad = 7.99;
326 double MuMetalCylinderOuterRad = 8.835;
327 double MuMetalCylinderLength = 75;
328
329 double PmtRadius = 5;
330 double PmtCenterPosition = 125.5;
331 double PmtWindowThickness = 1.2;
332
333 double PeekCapInnerRad = 1.6;
334 double PeekCapOuterRad = 8.835;
335 double PeekCapLength = 2.8;
336
337 double MetalConnectorOuterRad = 1.6;
338 double MetalConnectorLength = 9.8;
339
340 GeoShape* aShape = new GeoTube(0, PmtRadius, PmtWindowThickness/2);
341 GeoLogVol* logVol = new GeoLogVol("lvPmt", aShape, m_quartz);
342 GeoPhysVol* phyVol = new GeoPhysVol(logVol);
343
344 GeoShape* aShapeMu = new GeoTube(MUMetalCylinderInnerRad, MuMetalCylinderOuterRad, MuMetalCylinderLength/2);
345 GeoLogVol* logVolMu = new GeoLogVol("lvMuMetalCylinder", aShapeMu, m_materialManager->getMaterial("std::Iron"));
346 GeoPhysVol* phyVolMu = new GeoPhysVol(logVolMu);
347
348 GeoShape* aShapePeekCap = new GeoTube(PeekCapInnerRad, PeekCapOuterRad, PeekCapLength/2);
349 GeoLogVol* logVolPeekCap = new GeoLogVol("lvPmtPeekCap", aShapePeekCap, m_peek);
350 GeoPhysVol* phyVolPeekCap = new GeoPhysVol(logVolPeekCap);
351
352 GeoShape* aShapeMetalconnector = new GeoTube(0, MetalConnectorOuterRad, MetalConnectorLength/2);
353 GeoLogVol* logVolMetalConnector = new GeoLogVol("lvPmtMetalConnector", aShapeMetalconnector, m_materialManager->getMaterial("std::Iron"));
354 GeoPhysVol* phyVolMetalConnector = new GeoPhysVol(logVolMetalConnector);
355
356 double phi = M_PI/6*Gaudi::Units::rad;
357 int nSections = 4;
358 int nPmtTubesPerSection = 4;
359
360 for (int sec=0; sec<nSections; sec++) {
361 for (int tub=0; tub<nPmtTubesPerSection; tub++) {
362
363 double x = PmtCenterPosition*cos(phi/Gaudi::Units::rad);
364 double y = PmtCenterPosition*sin(phi/Gaudi::Units::rad);
365 double z = (16970-13442)+(PmtWindowThickness/2);
366 double zMu = (16963-13442)+(MuMetalCylinderLength/2);
367 double zCap = (16963-13442)-(PeekCapLength/2);
368 double zMetal = (16963-13442)-(MetalConnectorLength/2);
369
370 char sname[256]; sprintf(sname, "LucidPmt%d", 4*sec+tub);
371
372 log << MSG::INFO
373 << format("Adding %11s phi:%10.3f x:%10.3f y:%10.3f z:%10.3f", sname, phi, x, y, z)
374 << endmsg;
375
376 parent->add(new GeoNameTag (sname));
377 parent->add(new GeoTransform(GeoTrf::Translate3D(x, y, z)));
378 parent->add(phyVol);
379
380 char snameMu[256]; sprintf(snameMu, "MuMetal cylinder%d", 4*sec+tub);
381
382 log << MSG::INFO
383 << format("Adding %11s phi:%10.3f x:%10.3f y:%10.3f zMu:%10.3f", snameMu, phi, x, y, zMu)
384 << endmsg;
385
386 parent->add(new GeoNameTag (snameMu));
387 parent->add(new GeoTransform(GeoTrf::Translate3D(x, y, zMu)));
388 parent->add(phyVolMu);
389
390 char snamePeekCap[256]; sprintf(snamePeekCap, "PmtPeekCap%d", 4*sec+tub);
391
392 log << MSG::INFO
393 << format("Adding %11s phi:%10.3f x:%10.3f y:%10.3f zCap:%10.3f", snamePeekCap, phi, x, y, zCap)
394 << endmsg;
395
396 parent->add(new GeoNameTag (snamePeekCap));
397 parent->add(new GeoTransform(GeoTrf::Translate3D(x, y, zCap)));
398 parent->add(phyVolPeekCap);
399
400 char snameMetalConnector[256]; sprintf(snameMetalConnector, "MetalConnector%d", 4*sec+tub);
401
402 log << MSG::INFO
403 << format("Adding %11s phi:%10.3f x:%10.3f y:%10.3f zMetal:%10.3f", snameMetalConnector, phi, x, y, zMetal)
404 << endmsg;
405
406 parent->add(new GeoNameTag (snameMetalConnector));
407 parent->add(new GeoTransform(GeoTrf::Translate3D(x, y, zMetal)));
408 parent->add(phyVolMetalConnector);
409
410 phi = phi+(M_PI/18)*Gaudi::Units::rad;
411 }
412 phi = phi+(5* M_PI/18)*Gaudi::Units::rad;
413 }
414}
415
#define M_PI
Scalar phi() const
phi method
#define endmsg
@ stateSolid
double GetRefIndexQuartz(double lambda)
Definition of the abstract IRDBAccessSvc interface.
#define y
#define x
#define z
void AddProperty(const char *key, double *PhotonMomenta, double *PropertyValues, int NumEntries)
IRDBAccessSvc is an abstract interface to the athena service that provides the following functionalit...
virtual const LUCID_DetectorManager * getDetectorManager() const
StoredMaterialManager * m_materialManager
LUCID_DetectorFactory(StoreGateSvc *pDetStore, IRDBAccessSvc *pAccess)
void addLucidSupportCylinder(GeoFullPhysVol *)
LUCID_DetectorManager * m_detectorManager
void addPmtSupportCylinder(GeoFullPhysVol *)
void addVJconeFrontRing(GeoFullPhysVol *)
void addPmtTubes(GeoFullPhysVol *)
void addVJcone(GeoFullPhysVol *)
void addPmtSupport(GeoFullPhysVol *)
virtual void create(GeoPhysVol *)
void addVJconeBackRing(GeoFullPhysVol *)
GeoExtendedMaterial * m_quartz
The Athena Transient Store API.
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)