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