ATLAS Offline Software
Loading...
Searching...
No Matches
VolumeBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4
9#include "GeoModelKernel/GeoLogVol.h"
10#include "GeoModelKernel/GeoPhysVol.h"
11#include "GeoModelKernel/GeoFullPhysVol.h"
12#include "GeoModelKernel/GeoMaterial.h"
13#include "GeoModelKernel/GeoTransform.h"
14#include "GeoModelKernel/GeoDefinitions.h"
15#include "GaudiKernel/SystemOfUnits.h"
16
17
18namespace InDetDD {
20 VolumeBuilder::VolumeBuilder(const Zone& zone, const std::vector<const ServiceVolume* >& services)
21 : AthMessaging("InDetDDVolumeBuilder"),
22 m_region("None"), // Empty refers to a valid region. Set some default so we can check it is actually set.
23 m_zcenter(0),
24 m_services(nullptr),
25 m_servEnvelope(nullptr),
26 m_servChild(nullptr),
27 m_matManager(nullptr) {
28 m_splitter.splitAll(zone, services);
29 }
30
31 VolumeBuilder::VolumeBuilder(const std::vector<const ServiceVolume* >& services)
32 : AthMessaging("InDetDDVolumeBuilder"),
33 m_region("None"), // Empty refers to a valid region. Set some default so we can check it is actually set.
34 m_zcenter(0),
36 m_servEnvelope(nullptr),
37 m_servChild(nullptr),
38 m_matManager(nullptr)
39 {}
40
41 VolumeBuilder::VolumeBuilder(const Zone& zone, const std::vector<const ServiceVolume* >& services,
42 const std::vector<const ServiceVolume* >& servEnvelope,
43 const std::vector<const ServiceVolume* >& servChild)
44 : AthMessaging("InDetDDVolumeBuilder"),
45 m_region("None"), // Empty refers to a valid region. Set some default so we can check it is actually set.
46 m_zcenter(0),
47 m_services(nullptr),
48 m_servEnvelope(&servEnvelope),
49 m_servChild(&servChild),
50 m_matManager(nullptr) {
51 m_splitter.splitAll(zone, services);
52 }
53
54 void
55 VolumeBuilder::addServices(const Zone& zone, const std::vector<const ServiceVolume* >& services) {
56 m_splitter.splitAll(zone, services);
57 }
58
59 void
60 VolumeBuilder::setRegion(const std::string& region, double zcenter) {
61 m_region = region;
62 m_zcenter = zcenter;
63 }
64
65 const std::vector<const ServiceVolume* >&
67 // Return volumes defined in VolumeSplitter
68 if (m_services) return *m_services;
69 return m_splitter.getVolumes();
70 }
71
72 const std::vector<const ServiceVolume* >&
76
77 const std::vector<const ServiceVolume* >&
81
82 void
83 VolumeBuilder::buildAndPlace(const std::string& region, GeoPhysVol* parent, double zcenter) {
84 // Get volumes defined by Volume splitter and add them on top GeoPhysVol
85 setRegion(region, zcenter);
86 for (unsigned int iElement = 0; iElement < services().size(); ++iElement)
87 if (!isEnvelopeOrChild(iElement)) {
88 PhysVolPtr physVol{build(iElement)};
89 if (physVol) {
90 for (int iCopy = 0; iCopy < numCopies(iElement); ++iCopy) {
91 parent->add(getPlacement(iElement, iCopy));
92 parent->add(physVol);
93 }
94 }
95 }
96 }
97
98 void
99 VolumeBuilder::buildAndPlace(const std::string& region, GeoFullPhysVol* parent, double zcenter) {
100 // Get volumes defined by Volume splitter and add them on top GeoPhysVol
101 setRegion(region, zcenter);
102 for (unsigned int iElement = 0; iElement < services().size(); ++iElement) {
103 if (!isEnvelopeOrChild(iElement)) {
104 PhysVolPtr physVol{build(iElement)};
105 if (physVol) {
106 for (int iCopy = 0; iCopy < numCopies(iElement); ++iCopy) {
107 parent->add(getPlacement(iElement, iCopy));
108 parent->add(physVol);
109 }
110 }
111 }
112 }
113 // if region is not Pixel -> stop here
114 if (region.compare("Pixel") != 0) return;
115
116 for (unsigned int iElement = 0; iElement < services().size(); ++iElement) {
117 if (getEnvelopeNum(iElement) > 0 && services()[iElement]->envelopeParent() == 0) {
118 buildAndPlaceEnvelope(region, parent, -1, iElement, zcenter);
119 }
120 }
121 }
122
123 void
124 VolumeBuilder::buildAndPlaceEnvelope(const std::string& region, GeoFullPhysVol* parent, int iParent, int iElement,
125 double zcenter) {
126 PhysVolPtr physVol{build(iElement)};
127 if (physVol) {
128 for (unsigned int iChild = 0; iChild < services().size(); ++iChild) {
129 if (isChildService(iElement, iChild) && services()[iChild]->envelopeNum() > 0) {
130 // if volume is a child volume : build and place it
131 buildAndPlaceEnvelope(region, physVol, iElement, iChild, zcenter);
132 }
133 }
134 for (unsigned int iChild = 0; iChild < services().size(); ++iChild) {
135 if (isChildService(iElement, iChild) && services()[iChild]->envelopeNum() == 0) {
136 // if volume is not a child volume
137 PhysVolPtr physVol_child{build(iChild)};
138 if (physVol_child) {
139 for (int iCopy2 = 0; iCopy2 < numCopies(iChild); ++iCopy2) {
140 physVol->add(getPlacementEnvelope(iChild, iCopy2, iElement));
141 physVol->add(physVol_child);
142 }
143 }
144 }
145 }
146 for (int iCopy = 0; iCopy < numCopies(iElement); ++iCopy) {
147 // add all the copies
148 if (iParent < 0) parent->add(getPlacement(iElement, iCopy));
149 else parent->add(getPlacementEnvelope(iElement, iCopy, iParent));
150 parent->add(physVol);
151 }
152 }
153 }
154
155 void
156 VolumeBuilder::buildAndPlaceEnvelope(const std::string& region, GeoPhysVol* parent, int iParent, int iElement,
157 double zcenter) {
158 PhysVolPtr physVol{build(iElement)};
159 if (physVol) {
160 for (unsigned int iChild = 0; iChild < services().size(); ++iChild) {
161 if (isChildService(iElement, iChild) && services()[iChild]->envelopeNum() > 0) {
162 // if volume is a child volume : build and place it
163 buildAndPlaceEnvelope(region, physVol, iElement, iChild, zcenter);
164 }
165 }
166 for (unsigned int iChild = 0; iChild < services().size(); ++iChild) {
167 if (isChildService(iElement, iChild) && services()[iChild]->envelopeNum() == 0) {
168 // if volume is not a child volume
169 PhysVolPtr physVol_child{build(iChild)};
170 if (physVol_child) {
171 for (int iCopy2 = 0; iCopy2 < numCopies(iChild); ++iCopy2) {
172 physVol->add(getPlacementEnvelope(iChild, iCopy2, iElement));
173 physVol->add(physVol_child);
174 }
175 }
176 }
177 }
178 for (int iCopy = 0; iCopy < numCopies(iElement); ++iCopy) {
179 // add all the copies
180 if (iParent < 0) parent->add(getPlacement(iElement, iCopy));
181 else parent->add(getPlacementEnvelope(iElement, iCopy, iParent));
182 parent->add(physVol);
183 }
184 }
185 }
186
188 if (m_region == "None") {
189 ATH_MSG_ERROR("No region set. Cannot build services");
190 return nullptr;
191 }
192 const ServiceVolume& param = *(services()[iElement]);
193 // If the subelement does not belong to the current region return 0.
194 if (param.region() != m_region) return nullptr;
195
196 const GeoShape* serviceShape = param.getShape();
197 double volume = param.origVolume();
198 std::string logName = param.fullLabel();
199 const GeoMaterial* serviceMat = param.material();
200 std::string materialName;
201 if (!serviceMat) {
202 materialName = param.materialName();
203 if (m_matManager) {
204 //serviceMat = m_matManager->getMaterialForVolume(materialName,volume/param.fractionInRegion());
205 // FIXME
206 serviceMat = m_matManager->getMaterialForVolume(materialName, volume);
207 } else {
208 ATH_MSG_ERROR("Material manager not available. Cannot build material.");
209 return nullptr;
210 }
211 } else {
212 materialName = serviceMat->getName();
213 }
214 if (msgLvl(MSG::DEBUG)) {
215 msg(MSG::DEBUG) << "Volume/material: " << logName << "/" << materialName << endmsg;
216 if (!param.shapeType().empty()) msg(MSG::DEBUG) << " shape: " << param.shapeType() << endmsg;
217 msg(MSG::DEBUG) << " volume (cm3): " << volume / Gaudi::Units::cm3 << endmsg;
218 msg(MSG::DEBUG) << " rmin,rmax,zmin,zmax: "
219 << param.rmin() << ", "
220 << param.rmax() << ", "
221 << param.zmin() << ", "
222 << param.zmax() << endmsg;
223 }
224 // Or use volume of original volume in param.
225 //const GeoMaterial* serviceMat = mat_mgr->getMaterialForVolume(param.material(),param.origVolume());
226 GeoLogVol* serviceLog = new GeoLogVol(logName, serviceShape, serviceMat);
227 PhysVolPtr servicePhys{new GeoPhysVol(serviceLog)};
228 return servicePhys;
229 }
230
231 bool
233 const ServiceVolume& param = *(services()[iElement]);
234 return !(param.envelopeNum() == 0 && param.envelopeParent() == 0);
235 }
236
237 int
239 const ServiceVolume& param = *(services()[iElement]);
240 return param.envelopeNum();
241 }
242
243 int
245 const ServiceVolume& param = *(services()[iElement]);
246 return param.envelopeParent();
247 }
248
249 double
251 const ServiceVolume& param = *(services()[iElement]);
252 return (param.zmin() + param.zmax()) * 0.5;
253 }
254
255 bool
256 VolumeBuilder::isChildService(int iElt, int iChld) {
257 const ServiceVolume& param1 = *(services()[iElt]);
258 const ServiceVolume& param2 = *(services()[iChld]);
259 if (iElt == iChld || param1.envelopeNum() != param2.envelopeParent()) return false;
260 if (param1.zsymm() == 1) {
261 double zmin = (param1.zmin() * param2.zmin());
262 double zmax = (param1.zmax() * param2.zmax());
263 return zmin > 0 && zmax > 0;
264 }
265 return true;
266 }
267
268 int
270 return services()[iElement]->nCopies();
271 }
272
273 GeoTransform*
274 VolumeBuilder::getPlacement(int iElement, int iCopy) {
275 const ServiceVolume& param = *(services()[iElement]);
276 // NB. Corrected for placement in endcaps
277 double zpos = param.zposition() - m_zcenter;
278 // Shift along Z axis ( IBL shift )
279 double zshift = param.zShift();
280 zpos += zshift;
281 // Check if we need to rotate around Y axis.
282 bool rotateAroundY = false;
283 if (param.needsRotation()) { // zpos will always be negative in this case
284 zpos = -zpos;
285 rotateAroundY = true;
286 }
287 // Most are just translated in z
288 GeoTrf::Transform3D xform = GeoTrf::TranslateZ3D(zpos);
289 double phiStart = 0;
290 // BOX, ROD and TRAP need special treatment.
291 const std::string& shapeType = param.shapeType();
292 if (shapeType == "TRAP" || shapeType == "TRAP2") {
293 // Need to rotate by -90 deg.
294 xform = GeoTrf::RotateZ3D(-90. * Gaudi::Units::deg) * xform;
295 }
296 if (shapeType == "TRAP2") {
297 xform = GeoTrf::RotateZ3D(-90. * Gaudi::Units::deg) * xform; // * GeoTrf::RotateX3D(-90.*Gaudi::Units::deg);
298 }
299 if (shapeType == "BOX" || shapeType == "TRAP" || shapeType == "TRAP2") {
300 double radius = 0.5 * (param.rmin() + param.rmax());
301 xform = GeoTrf::TranslateX3D(radius) * xform;
302 phiStart = param.phiLoc();
303 } else if (shapeType == "ROD" || shapeType == "ROD2") {
304 double radius = param.rmin();
305 xform = GeoTrf::TranslateX3D(radius) * xform;
306 phiStart = param.phiLoc();
307 }
308 // For volumes that are placed more than once.
309 double deltaPhi = 0;
310 if (iCopy > 0) {
311 deltaPhi = 2. * M_PI / param.nCopies();
312 }
313 double phi = phiStart + deltaPhi * iCopy;
314 if (phi) {
315 xform = GeoTrf::RotateZ3D(phi) * xform;
316 }
317 // For shapes that are not symmetric about a rotation around Y axis. We need to rotate.
318 if (rotateAroundY) {
319 xform = GeoTrf::RotateY3D(180. * Gaudi::Units::degree) * xform;
320 }
321 return new GeoTransform(xform);
322 }
323
324 GeoTransform*
325 VolumeBuilder::getPlacementEnvelope(int iElement, int iCopy, int iEnvElement) {
326 const ServiceVolume& param = *(services()[iElement]);
327 const ServiceVolume& paramEnv = *(services()[iEnvElement]);
328 double zCenter = (paramEnv.zmin() + paramEnv.zmax()) * 0.5;
329 double rCenter = 0.;
330 bool bMoveToCenter = false;
331 if (paramEnv.shapeType() == "BOX") bMoveToCenter = true;
332 if (paramEnv.shapeType() == "TUBE" && paramEnv.zsymm() == 1 && fabs(paramEnv.zmin()) > 0.01) bMoveToCenter = true;
333 if (bMoveToCenter) rCenter = (paramEnv.rmin() + paramEnv.rmax()) * 0.5;
334 // NB. Corrected for placement in endcaps
335 double zpos = param.zposition() - zCenter;
336 // Check if we need to rotate around Y axis.
337 bool rotateAroundY = false;
338 if (param.needsRotation()) { // zpos will always be negative in this case
339 zpos = -zpos;
340 rotateAroundY = true;
341 }
342 // Most are just translated in z
343 GeoTrf::Transform3D xform = GeoTrf::TranslateZ3D(zpos);
344 const std::string& shapeType = param.shapeType();
345 double phiStart = 0;
346 // BOX, ROD and TRAP need special treatment.
347 if (shapeType == "TRAP") {
348 // Need to rotate by -90 deg.
349 xform = GeoTrf::RotateZ3D(-90. * Gaudi::Units::deg) * xform;
350 }
351 if (shapeType == "TRAP2") {
352 // Need to rotate by -90 deg.
353 xform = GeoTrf::RotateX3D(-90. * Gaudi::Units::deg) * xform;
354 }
355 if (shapeType == "BOX" || shapeType == "TRAP" || shapeType == "TRAP2") {
356 double radius = 0.5 * (param.rmin() + param.rmax()) - rCenter;
357 xform = GeoTrf::TranslateX3D(radius) * xform;
358 phiStart = param.phiLoc();
359 } else if (shapeType == "ROD" || shapeType == "ROD2") {
360 double radius = param.rmin();
361 xform = GeoTrf::TranslateX3D(radius) * xform;
362 phiStart = param.phiLoc();
363 }
364 // For volumes that are placed more than once.
365 double deltaPhi = 0;
366 if (iCopy > 0) {
367 deltaPhi = 2. * M_PI / param.nCopies();
368 }
369 double phi = phiStart + deltaPhi * iCopy;
370 if (phi) {
371 xform = GeoTrf::RotateZ3D(phi) * xform;
372 }
373 // For shapes that are not symmetric about a rotation around Y axis. We need to rotate.
374 if (rotateAroundY) {
375 xform = GeoTrf::RotateY3D(180. * Gaudi::Units::degree) * xform;
376 }
377 return new GeoTransform(xform);
378 }
379} // end namespace
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
#define endmsg
#define ATH_MSG_ERROR(x)
MsgStream & msg() const
The standard message stream.
bool msgLvl(const MSG::Level lvl) const
Test the output level.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
GeoTransform * getPlacementEnvelope(int iElement, int iCopy, int iMothElement)
void buildAndPlace(const std::string &region, GeoPhysVol *parent, double zcenter=0)
VolumeBuilder(const Zone &zone, const std::vector< const ServiceVolume * > &services)
double getZcenter(int iElt)
bool isEnvelopeOrChild(int iElement)
bool isChildService(int iElt, int iChld)
const std::vector< const ServiceVolume * > & servicesChild()
void setRegion(const std::string &region, double zcenter)
void buildAndPlaceEnvelope(const std::string &region, GeoFullPhysVol *parent, int iParent, int iElement, double zcenter=0)
void addServices(const Zone &zone, const std::vector< const ServiceVolume * > &services)
PhysVolPtr build(int iElement)
GeoTransform * getPlacement(int iElement, int iCopy)
const std::vector< const ServiceVolume * > & servicesEnv()
const std::vector< const ServiceVolume * > & services()
int getEnvelopeNum(int iElement)
int numCopies(int iElement)
int getParentNum(int iElement)
Message Stream Member.
VolumeBuilder::PhysVolPtr PhysVolPtr