ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_Ski.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#include "SCT_Ski.h"
6#include "SCT_Identifier.h"
11#include "SCT_Module.h"
12#include "SCT_BaseBoard.h"
13#include "SCT_Dogleg.h"
14#include "SCT_CoolingBlock.h"
15#include "SCT_CoolingPipe.h"
16
18
19#include "GeoModelRead/ReadGeoModel.h"
20#include "GeoModelKernel/GeoBox.h"
21#include "GeoModelKernel/GeoTube.h"
22#include "GeoModelKernel/GeoLogVol.h"
23#include "GeoModelKernel/GeoPhysVol.h"
24#include "GeoModelKernel/GeoNameTag.h"
25#include "GeoModelKernel/GeoIdentifierTag.h"
26#include "GeoModelKernel/GeoTransform.h"
27#include "GeoModelKernel/GeoAlignableTransform.h"
28#include "GeoModelKernel/GeoMaterial.h"
29#include "GeoModelKernel/GeoShape.h"
30#include "GeoModelKernel/GeoShapeUnion.h"
31#include "GeoModelKernel/GeoShapeShift.h"
32#include "GeoModelKernel/GeoDefinitions.h"
33#include "GaudiKernel/SystemOfUnits.h"
34
35#include <cmath>
36#include <sstream>
37#include <utility>
38
39SCT_Ski::SCT_Ski(const std::string & name,
41 int stereoSign,
42 double tilt,
43 double length,
44 InDetDD::SCT_DetectorManager* detectorManager,
45 SCT_GeometryManager* geometryManager,
46 SCT_MaterialManager* materials,
47 GeoModelIO::ReadGeoModel* sqliteReader,
48 std::shared_ptr<std::map<std::string, GeoFullPhysVol*>> mapFPV,
49 std::shared_ptr<std::map<std::string, GeoAlignableTransform*>> mapAX)
50 : SCT_UniqueComponentFactory(name, detectorManager, geometryManager, materials, sqliteReader, std::move(mapFPV), std::move(mapAX)),
52 m_tilt(tilt),
55{
57 if(!m_sqliteReader) {
59 }
60}
61
62
63SCT_Ski::~SCT_Ski() = default;
64
65void
67{
68
69 const SCT_BarrelParameters * parameters = m_geometryManager->barrelParameters();
70 const SCT_GeneralParameters * generalParameters = m_geometryManager->generalParameters();
71
72 m_safety = generalParameters->safety();
73
74 m_radialSep = parameters->skiRadialSep();
75 m_firstStagger = parameters->skiFirstStagger();
76 m_modulesPerSki = parameters->modulesPerSki();
77 for (int iModule = 0; iModule < m_modulesPerSki; iModule++){
78 m_zPos.push_back(parameters->skiZPosition(iModule));
79 m_id.push_back(parameters->skiModuleIdentifier(iModule));
80 }
81
82 // Various offset for the doglegs, cooling blocks and cooling pipe.
83 // These are not currently needed and are all set to zero.
90
91 m_coolingBlockOffsetX = parameters->coolingBlockOffsetX();
92 m_coolingBlockOffsetY = parameters->coolingBlockOffsetY();
93 m_coolingBlockOffsetZ = parameters->coolingBlockOffsetZ();
94 m_coolingPipeOffsetX = parameters->coolingPipeOffsetX();
95 m_coolingPipeOffsetY = parameters->coolingPipeOffsetY();
96
97 m_doglegOffsetX = parameters->doglegOffsetX();
98 m_doglegOffsetY = parameters->doglegOffsetY();
99}
100
101const GeoLogVol *
103{
104 const double rphiClearance = 0.5*Gaudi::Units::mm;
105 const double radialClearance = 0.5*Gaudi::Units::mm;
106
107
108 // Make components.
109 m_dogleg = std::make_unique<SCT_Dogleg>(getName()+"Dogleg", m_detectorManager, m_geometryManager, m_materials);
110 m_coolingBlock = std::make_unique<SCT_CoolingBlock>(getName()+"CoolingBlock",
112 m_coolingPipe = std::make_unique<SCT_CoolingPipe>(getName()+"CoolingPipe", m_length,
114
115 // We need the sign of the tilt in numerous places
116 int tiltSign = (m_tilt < 0) ? -1 : +1;
117
118
119 // The two modules are lined up in x in the unrotated ski. The ski then gets tilted
120 // when placed in the layer.
121 // So the x offset is just the raidal separation and the y offset is zero.
122
123 double xModuleOffset = 0.5 * m_radialSep;
124
125 double yModuleOffset = 0.0;
126
127
128 //
129 // Calculate position of cooling block
130 //
131 // Position the cooling block m_coolingBlockPhiOffset from the lower egde
132 // of the module and m_coolingBlockRadialOffset from surface of the module.
133
134 double xCoolingBlockOffset = - m_coolingBlockRadialOffset + coolingBlockOffsetX();
135 double yCoolingBlockOffset = tiltSign *(coolingBlockOffsetY() - m_coolingBlockPhiOffset);
136 double zCoolingBlockOffset = coolingBlockOffsetZ();
137
138 //
139 // Calculate position of dogleg
140 //
141
142 double xDoglegOffset = doglegOffsetX() - m_doglegRadialOffset;
143
144 // NB length of dogleg runs in phi direction.
145 double yDoglegOffset = tiltSign * (doglegOffsetY() + m_doglegPhiOffset);
146
147 double zDoglegOffset = coolingBlockOffsetZ();
148
149 //
150 // Calculate position of cooling pipe.
151 //
152 double xCoolingPipePos = coolingPipeOffsetX() - m_coolingPipeRadialOffset;
153 double yCoolingPipePos = coolingPipeOffsetY() + m_coolingPipePhiOffset;
154 m_coolingPipePos = new GeoTransform(GeoTrf::Translate3D(xCoolingPipePos, yCoolingPipePos, 0));
155 //
156 //
157 //
158
159 int stagger_sign = m_firstStagger;
160 // Loop over modules in ski as we need their z positions.
161 for (int iModule = 0; iModule < m_modulesPerSki; iModule++) {
162
163 // For compatibility with AGE we need to offset the module in y by -0.5*sep*sin(tilt) so that center
164 // of module lines up with radial line. (Not sure if this is what is done in reality)
165
166 // Not sure if this needs to be alignable
167 double xModulePos = stagger_sign * xModuleOffset;
168 double yModulePos = yModuleOffset;
169 double zModulePos = m_zPos[iModule];
170
171 // There is only one type of module and this is rotated one way or the other
172 // to get the phi-v (-ve), u-phi (+ve) orientations
173 GeoTrf::RotateX3D rot(0.5 * m_stereoSign * m_module->stereoAngle());
174 GeoTrf::Translation3D pos(xModulePos, yModulePos, zModulePos);
175 m_modulePos.push_back(GeoTrf::Transform3D(pos*rot));
176
177 //
178 // Calculate position of cooling block
179 //
180
181 double xCoolingBlockPos = xCoolingBlockOffset + xModulePos;
182 double yCoolingBlockPos = yCoolingBlockOffset + yModulePos;
183 double zCoolingBlockPos = zCoolingBlockOffset + zModulePos;
184 m_coolingBlockPos.push_back(new GeoTransform(GeoTrf::Translate3D(xCoolingBlockPos, yCoolingBlockPos, zCoolingBlockPos)));
185
186
187 //
188 // Calculate position of dogleg
189 //
190 double xDoglegPos = xDoglegOffset + xModulePos;
191 double yDoglegPos = yDoglegOffset + yModulePos;
192 double zDoglegPos = zDoglegOffset + zModulePos;
193 m_doglegPos.push_back(new GeoTransform(GeoTrf::Translate3D(xDoglegPos, yDoglegPos, zDoglegPos)));
194
195 // alternate staggering
196 stagger_sign = - stagger_sign;
197
198
199 }
200
201 //
202 // calculate envelope for ski with just modules. Not all these are used.
203 // These are coordinates of corners of module's envelopes.
204 //
205
206 GeoTrf::Vector3D c0(0.0,
207 -(m_module->env1RefPointVector()->y()) + 0.5*(m_module->env1Width()),
208 -(m_module->env1RefPointVector()->z()) + 0.5*(m_module->env1Length()));
209 GeoTrf::Vector3D c1(0.0,
210 -(m_module->env1RefPointVector()->y()) - 0.5*(m_module->env1Width()),
211 -(m_module->env1RefPointVector()->z()) + 0.5*(m_module->env1Length()));
212 GeoTrf::Vector3D c2(0.0,
213 -(m_module->env1RefPointVector()->y()) - 0.5*(m_module->env1Width()),
214 -(m_module->env1RefPointVector()->z()) - 0.5*(m_module->env1Length()));
215 GeoTrf::Vector3D c3(0.0,
216 -(m_module->env1RefPointVector()->y()) + 0.5*(m_module->env1Width()),
217 -(m_module->env1RefPointVector()->z()) - 0.5*(m_module->env1Length()));
218 GeoTrf::Vector3D c4(0.0,
219 -(m_module->env2RefPointVector()->y()) + 0.5*(m_module->env2Width()),
220 -(m_module->env2RefPointVector()->z()) + 0.5*(m_module->env2Length()));
221 GeoTrf::Vector3D c5(0.0,
222 -(m_module->env2RefPointVector()->y()) - 0.5*(m_module->env2Width()),
223 -(m_module->env2RefPointVector()->z()) + 0.5*(m_module->env2Length()));
224 GeoTrf::Vector3D c6(0.0,
225 -(m_module->env2RefPointVector()->y()) - 0.5*(m_module->env2Width()),
226 -(m_module->env2RefPointVector()->z()) - 0.5*(m_module->env2Length()));
227 GeoTrf::Vector3D c7(0.0,
228 -(m_module->env2RefPointVector()->y()) + 0.5*(m_module->env2Width()),
229 -(m_module->env2RefPointVector()->z()) - 0.5*(m_module->env2Length()));
230
231 double moduleYMax = c4.y();
232 double moduleYMin = c5.y();
233 c0 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c0;
234 c1 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c1;
235 c2 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c2;
236 c3 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c3;
237 c4 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c4;
238 c5 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c5;
239 c6 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c6;
240 c7 = GeoTrf::RotateX3D(0.5 * m_stereoSign * m_module->stereoAngle())*c7;
241
242 moduleYMax = std::max(std::max(c0.y(), c4.y()), std::max(c7.y(), c3.y()));
243 moduleYMin = std::min(std::min(c1.y(), c5.y()), std::min(c6.y(), c2.y()));
244
245 double skiWidth = moduleYMax - moduleYMin + 2*rphiClearance;
246
247 //
248 // NB. The envelope is centered on x.
249 //
250 double skiThickness = m_module->thickness() + 2 * std::abs(xModuleOffset) + radialClearance;
251
252 // Due to the cooling block and dogleg being next to the module and
253 // as the modules are staggered it is no longer possible to have a
254 // simple envelope around the ski.
255
256 // Calculate envelope needed. This is a boolean of two rectangles.
257 // 1. Contains the modules and dogleg.
258 // 2. Contains the cooling pipe and cooling block.
259
260 double xmax1 = 0.5*skiThickness;
261 double xmin1 = -xModuleOffset + xDoglegOffset - 0.5*m_dogleg->thickness();
262 double xmax2 = xmax1;
263 double xmin2 = xCoolingPipePos - m_coolingPipe->pipeRadius();
264
265 // Take into account possiblity that the dogleg extends past the module.
266
267 double ymax1 = moduleYMax + rphiClearance;
268 double ymin1 = moduleYMin - rphiClearance;
269 double ymin2,ymax2;
270 if (tiltSign > 0) {
271 ymax2 = std::max(-yModuleOffset + yCoolingBlockOffset + 0.5*m_coolingBlock->width(),
272 yCoolingPipePos + m_coolingPipe->pipeRadius());
273 ymin2 = ymin1;
274 } else {
275 ymax2 = ymax1;
276 ymin2 = std::min(-yModuleOffset + yCoolingBlockOffset - 0.5*m_coolingBlock->width(),
277 yCoolingPipePos - m_coolingPipe->pipeRadius());
278 }
279
280
281 // Add some safety
282 xmin1 -= m_safety;
283 xmax1 += m_safety;
284 ymin1 -= m_safety;
285 ymax1 += m_safety;
286
287 xmin2 -= m_safety;
288 xmax2 += m_safety;
289 ymin2 -= m_safety;
290 ymax2 += m_safety;
291
292 double xCenter = 0.5*(xmin1+xmax1);
293 double yCenter = 0.5*(ymin1+ymax1);
294 double xShift2 = 0.5*(xmin2+xmax2) - xCenter;
295 double yShift2 = 0.5*(ymin2+ymax2) - yCenter;
296
297 m_refPointTransform = new GeoTransform(GeoTrf::Translate3D(-xCenter, -yCenter, 0));
298
299 m_env1RefPointVector = std::make_unique<GeoTrf::Vector3D>(-xCenter, -yCenter, 0.0);
300 m_env2RefPointVector = std::make_unique<GeoTrf::Vector3D>(-xShift2, -yShift2, 0.0);
301 m_env1Thickness = xmax1-xmin1;
302 m_env1Width = ymax1-ymin1;
303 m_env2Thickness = xmax2-xmin2;
304 m_env2Width = ymax2-ymin2;
305
306 GeoBox * envelope1 = new GeoBox(0.5 * (xmax1-xmin1), 0.5 * (ymax1-ymin1), 0.5 * m_length);
307 GeoBox * envelope2 = new GeoBox(0.5 * (xmax2-xmin2), 0.5 * (ymax2-ymin2), 0.5 * m_length);
308
309 const GeoShape * skiEnvelopeShape = nullptr;
310
311 const GeoShape & tmpShape = (*envelope1).
312 add(*envelope2 << GeoTrf::Translate3D(xShift2, yShift2, 0));
313 skiEnvelopeShape = &tmpShape;
314
315 GeoLogVol * skiLog = new GeoLogVol(getName(), skiEnvelopeShape, m_materials->gasMaterial());
316
317 // Make names once only so we don't recreate them again again.
318 for (int iModule = 0; iModule < m_modulesPerSki; iModule++) {
319 // Add identifier to name.
320 std::ostringstream name;
321 name << "Module#" << m_id[iModule];
322 m_nameTag.push_back(new GeoNameTag(name.str()));
323 }
324
325
326 // Define thickness, width, and length. This is chosen as bounding box centered on the ski rotation axis
327 // which contains the modules and dogleg (ie cooling blocks and cooling pipe is ignored.)
328 m_thickness = 2 * std::abs(xmin1);
329 m_width = skiWidth;
330
331
332 // Calculate the clearances. Module envelope1 is the thickness up to the sensors. This is used for the module to
333 // module distance
334
335 return skiLog;
336
337}
338
339
340GeoVPhysVol *
342{
343 GeoPhysVol * ski=nullptr;
344
345 if(!m_sqliteReader){
346
347 ski= new GeoPhysVol(m_logVolume);
348
349 for (int iModule = 0; iModule < m_modulesPerSki; iModule++) {
350
351 // Add modules.
352 ski->add(m_refPointTransform);
353 GeoAlignableTransform * moduleTransform = new GeoAlignableTransform(m_modulePos[iModule]);
354 ski->add(moduleTransform);
355 ski->add(m_nameTag[iModule]);
356 ski->add(new GeoIdentifierTag(m_id[iModule]));
357 id.setEtaModule(m_id[iModule]); // Set identifier.
358 GeoVPhysVol * modulePV = m_module->build(id);
359 ski->add(modulePV);
360
361 // Store alignable transform
362 m_detectorManager->addAlignableTransform(1, id.getWaferId(), moduleTransform, modulePV);
363
364 // Add dogleg
365 ski->add(m_refPointTransform);
366 ski->add(m_doglegPos[iModule]);
367 ski->add(m_dogleg->getVolume());
368
369 // and coolingblock
370 ski->add(m_refPointTransform);
371 ski->add(m_coolingBlockPos[iModule]);
372 ski->add(m_coolingBlock->getVolume());
373 }
374
375 // Add Cooling pipe
376 ski->add(m_refPointTransform);
377 ski->add(m_coolingPipePos);
378 ski->add(m_coolingPipe->getVolume());
379 }
380 else{
381
382 for (int iModule = 0; iModule < m_modulesPerSki; iModule++) {
383
384 // Add modules.
385 id.setEtaModule(m_id[iModule]); // Set identifier.
386 m_module->build(id);
387
388 std::string key="ModuleSKI_"+std::to_string(id.getLayerDisk())+"_"+std::to_string(id.getEtaModule())+"_"+std::to_string(id.getPhiModule());
389
390 // Store alignable transform
391 m_detectorManager->addAlignableTransform(1, id.getWaferId(), (*m_mapAX)[key], (*m_mapFPV)[key]);
392
393 }
394 }
395 return ski;
396}
Dedicated detector manager extending the functionality of the SiDetectorManager with dedicated SCT in...
const std::string & getName() const
InDetDD::SCT_DetectorManager * m_detectorManager
SCT_GeometryManager * m_geometryManager
SCT_MaterialManager * m_materials
double m_doglegPhiOffset
Definition SCT_Ski.h:107
double length() const
Definition SCT_Ski.h:50
int stereoSign() const
Definition SCT_Ski.h:59
std::vector< GeoTransform * > m_coolingBlockPos
Definition SCT_Ski.h:145
virtual const GeoLogVol * preBuild()
Definition SCT_Ski.cxx:102
double m_coolingBlockOffsetY
Definition SCT_Ski.h:116
std::unique_ptr< SCT_Dogleg > m_dogleg
Definition SCT_Ski.h:125
double doglegOffsetY() const
Definition SCT_Ski.h:80
double coolingBlockOffsetY() const
Definition SCT_Ski.h:74
double m_radialSep
Definition SCT_Ski.h:90
double m_length
Definition SCT_Ski.h:101
int m_firstStagger
Definition SCT_Ski.h:91
double m_coolingPipeOffsetX
Definition SCT_Ski.h:118
double m_env1Width
Definition SCT_Ski.h:138
double m_width
Definition SCT_Ski.h:102
std::vector< GeoTrf::Transform3D > m_modulePos
Definition SCT_Ski.h:143
double m_env1Thickness
Definition SCT_Ski.h:137
double m_coolingBlockOffsetX
Definition SCT_Ski.h:115
double m_doglegRadialOffset
Definition SCT_Ski.h:108
double coolingBlockOffsetZ() const
Definition SCT_Ski.h:75
std::unique_ptr< GeoTrf::Vector3D > m_env1RefPointVector
For calculations of envelopes of SCT_DetailLayer.
Definition SCT_Ski.h:133
std::vector< double > m_zPos
Definition SCT_Ski.h:95
double m_tilt
Definition SCT_Ski.h:99
double m_coolingPipeOffsetY
Definition SCT_Ski.h:119
double m_safety
Definition SCT_Ski.h:93
double coolingBlockOffsetX() const
Definition SCT_Ski.h:73
double m_coolingPipeRadialOffset
Definition SCT_Ski.h:111
int m_modulesPerSki
Definition SCT_Ski.h:92
double m_coolingPipePhiOffset
Definition SCT_Ski.h:112
SCT_Module * m_module
Definition SCT_Ski.h:124
void getParameters()
Definition SCT_Ski.cxx:66
double m_coolingBlockRadialOffset
Definition SCT_Ski.h:110
double m_env2Thickness
Definition SCT_Ski.h:139
std::vector< GeoNameTag * > m_nameTag
Definition SCT_Ski.h:142
const SCT_Module * module() const
Definition SCT_Ski.h:61
double coolingPipeOffsetY() const
Definition SCT_Ski.h:77
std::unique_ptr< SCT_CoolingBlock > m_coolingBlock
Definition SCT_Ski.h:126
GeoIntrusivePtr< GeoTransform > m_refPointTransform
Definition SCT_Ski.h:129
int m_stereoSign
Definition SCT_Ski.h:98
GeoIntrusivePtr< GeoTransform > m_coolingPipePos
Definition SCT_Ski.h:130
double m_coolingBlockPhiOffset
Definition SCT_Ski.h:109
std::unique_ptr< SCT_CoolingPipe > m_coolingPipe
Definition SCT_Ski.h:127
double tilt() const
Definition SCT_Ski.h:58
double doglegOffsetX() const
Definition SCT_Ski.h:79
std::unique_ptr< GeoTrf::Vector3D > m_env2RefPointVector
For calculations of envelopes of SCT_DetailLayer.
Definition SCT_Ski.h:135
double m_coolingBlockOffsetZ
Definition SCT_Ski.h:117
double m_doglegOffsetY
Definition SCT_Ski.h:122
std::vector< GeoTransform * > m_doglegPos
Definition SCT_Ski.h:144
double coolingPipeOffsetX() const
Definition SCT_Ski.h:76
std::vector< int > m_id
Definition SCT_Ski.h:96
double m_thickness
Definition SCT_Ski.h:103
double m_doglegOffsetX
Definition SCT_Ski.h:121
virtual GeoVPhysVol * build(SCT_Identifier id)
Definition SCT_Ski.cxx:341
double m_env2Width
Definition SCT_Ski.h:140
SCT_Ski(const std::string &name, SCT_Module *module, int stereoSign, double tilt, double length, InDetDD::SCT_DetectorManager *detectorManager, SCT_GeometryManager *geometryManager, SCT_MaterialManager *materials, GeoModelIO::ReadGeoModel *sqliteReader, std::shared_ptr< std::map< std::string, GeoFullPhysVol * > > mapFPV, std::shared_ptr< std::map< std::string, GeoAlignableTransform * > > mapAX)
Definition SCT_Ski.cxx:39
SCT_UniqueComponentFactory(const std::string &name, InDetDD::SCT_DetectorManager *detectorManager, SCT_GeometryManager *geometryManager, SCT_MaterialManager *materials=nullptr, GeoModelIO::ReadGeoModel *sqliteReader=nullptr, std::shared_ptr< std::map< std::string, GeoFullPhysVol * > > mapFPV=nullptr, std::shared_ptr< std::map< std::string, GeoAlignableTransform * > > mapAX=nullptr)
std::shared_ptr< std::map< std::string, GeoFullPhysVol * > > m_mapFPV
std::shared_ptr< std::map< std::string, GeoAlignableTransform * > > m_mapAX
GeoModelIO::ReadGeoModel * m_sqliteReader
bool add(const std::string &hname, TKey *tobj)
Definition fastadd.cxx:55
STL namespace.