ATLAS Offline Software
Loading...
Searching...
No Matches
InDetGeoModelUtils/src/ServiceVolume.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//
6// This class to hold general services
7//
8// The services support several different shapes. The meaning of the parameters
9// depends on the particular shape:
10//
11//
12// TUBE or empty
13// Ignored: RIN2,ROUT2,PHI,WIDTH,REPEAT
14// TUBS
15// Ignored: RIN2,ROUT2
16// PHI: phi start location of tube sector
17// WIDTH (CLHEP::deg): phi width of sector
18// REPEAT: Repeat the tube sector this many times in phi with equal distance between them.
19// CONS, CONE
20// WIDTH,REPEAT ignored if CONE
21// RIN2,ROUT2: rmin, rmx at zmax. Same as RIN, ROUT if <=0.
22// PHI, WIDTH, REPEAT same as TUBS
23// PGON
24// Ignored: WIDTH
25// RIN,ROUT,RIN2,ROUT2 defined at corner of polygon.
26// PHI: phi start location of a corner
27// REPEAT: Sides of polygon
28// PGON2
29// Ignored: WIDTH
30// RIN,ROUT,RIN2,ROUT2 defined at side of polygon.
31// PHI: phi start location of center of side.
32// REPEAT: Sides of polygon
33// PGON3 (pgon at outer edge, circular inner edge)
34// Ignored: WIDTH
35// RIN,RIN2 radius of inner edge (tube or cone)
36// ROUT,ROUT2 defined at corner of polygon.
37// PHI: phi start location of a corner
38// REPEAT: Sides of polygon
39// PGON31 (pgon at inner edge, circular outer edge)
40// Ignored: WIDTH
41// RIN,RIN2 radius of inner edge (tube or cone)
42// ROUT,ROUT2 defined at corner of polygon.
43// PHI: phi start location of a corner
44// REPEAT: Sides of polygon
45// PGON4 (pgon at outer edge, circular inner edge)
46// Ignored: WIDTH
47// RIN,RIN2 radius of inner edge (tube or cone)
48// ROUTROUT2 defined at side of polygon.
49// PHI: phi start location of center of side.
50// REPEAT: Sides of polygon
51// ROD
52// Ignored: ROUT, RIN2, ROUT2
53// RIN: Radial position of center of tube
54// PHI: phi position of center
55// WIDTH (mm): diameter
56// REPEAT: Repeat this many times in phi with equal distance between them.
57// ROD2 (hollow tube not centered around Z axis)
58// Ignored: ROUT, ROUT2
59// RIN: Radial position of center of tube
60// RIN2: inner radius
61// PHI: phi position of center
62// WIDTH (mm): diameter
63// REPEAT: Repeat this many times in phi with equal distance between them.
64// BOX
65// Ignored: RIN2, ROUT2
66// ROUT-RIN = thickness of box (radially)
67// (RIN+ROUT)/2 = radial poistion of center of box
68// PHI: phi position of center
69// WIDTH (mm) = width of box
70// REPEAT: Repeat this many times in phi with equal distance between them.
71// TRAP
72// Ignored: RIN2, ROUT2
73// ROUT-RIN = thickness of trapezoid (radially)
74// (RIN+ROUT)/2 = radial poistion of center of trapzoid
75// PHI: phi position of center
76// WIDTH (mm) = width of trapezoid at center
77// REPEAT: Repeat this many times in phi with equal distance between them.
78//
79// **IMPORTANT NOTE** WIDTH can be in degrees or mm. See OraclePixGeoManager
80
82#include "GeoModelKernel/GeoTube.h"
83#include "GeoModelKernel/GeoTubs.h"
84#include "GeoModelKernel/GeoCons.h"
85#include "GeoModelKernel/GeoPgon.h"
86#include "GeoModelKernel/GeoBox.h"
87#include "GeoModelKernel/GeoTrap.h"
88#include "GeoModelKernel/GeoShapeSubtraction.h"
89#include "GaudiKernel/SystemOfUnits.h"
90
91#include <format>
92#include <iostream>
93#include <string>
94
95namespace InDetDD {
97 : m_rmin(0),
98 m_rmax(0),
99 m_rmin2(0),
100 m_rmax2(0),
101 m_zmin(0),
102 m_zmax(0),
103 //m_volId(0),
104 m_zsymm(false),
105 m_geoShape(nullptr),
106 m_material(nullptr),
107 m_phiLoc(0),
108 m_phiWidth(0),
109 m_needsRotation(false),
110 m_sides(0),
111 m_nCopies(1),
112 //m_origLength(0),
113 m_origVolume(0),
114 m_volume(0),
115 m_safety(0),
117 m_splittableR(true),
118 m_splittableZ(true),
119 m_envNum(0),
121 m_zShift(0.),
122 m_mutex()
123 {}
124
126 : m_rmin(rhs.m_rmin),
127 m_rmax(rhs.m_rmax),
128 m_rmin2(rhs.m_rmin2),
129 m_rmax2(rhs.m_rmax2),
130 m_zmin(rhs.m_zmin),
131 m_zmax(rhs.m_zmax),
132 //m_volId(rhs.m_volId),
133 m_zsymm(rhs.m_zsymm),
134 m_geoShape(rhs.m_geoShape),
137 m_volName(rhs.m_volName),
139 m_phiLoc(rhs.m_phiLoc),
142 m_sides(rhs.m_sides),
143 m_nCopies(rhs.m_nCopies),
144 //m_origLength(rhs.m_origLength),
146 m_volume(rhs.m_volume),
147 m_safety(rhs.m_safety),
148 m_region(rhs.m_region),
149 m_label(rhs.m_label),
153 m_envNum(rhs.m_envNum),
155 m_zShift(rhs.m_zShift),
156 m_mutex()
157 {}
158
159 void
161 // Don't do anything if its a very thin volume.
162 if (length() > 4. * safety) {
164 m_safety = safety;
165 }
166 std::lock_guard<std::mutex> lock(m_mutex);
167 m_geoShape = nullptr;
168 }
169
170 void
171 ServiceVolume::setLabel(const std::string& name, int volId) {
172 m_label = std::format("{:s}{:02d}", name, volId);
173 }
174
175 std::string
177 if (m_volName.empty()) return m_label;
178
179 return m_label + "_" + m_volName;
180 }
181
182 void
184 std::cout << m_rmin << " "
185 << m_rmax << " "
186 << m_zmin << " "
187 << m_zmax << " "
188 << m_region << " "
189 << fullLabel()
190 << std::endl;
191 }
192
193 const GeoShape*
195 std::lock_guard<std::mutex> lock(m_mutex);
196
197 // If prebuilt then return
198 if (m_geoShape.get()) return m_geoShape.get();
199
200 //
201 // Dimensions
202 //
203 //double rmin = rmin();
204 //double rmax = rmax();
205 //double rmin2 = rmin2();
206 //double rmax2 = rmax2();
207 //double phiLoc = phiLoc();
208 //double phiWidth = phiWidth();
209 //int sides = sides();
210 //const std::string & shapeType = shapeType();
211
212 double halflength = 0.5 * length();
213
214 //std::cout << "Building service volume " << logName << ": "
215 // << rmin << ", "
216 // << rmax << ", "
217 // << halflength << ", "
218 // << materialName << std::endl;
219
220 const GeoShape* serviceShape = nullptr;
221 double volume = 0;
222
223 // Check if service needs to be shifted
224 // if(fabs(m_zShift)>0.001)
225 // std::cout<<"SHIFTED SERVICE : "<<m_volName<<" "<<m_shapeType<<std::endl;
226
227 if (m_shapeType.empty() || m_shapeType == "TUBE") {
228 serviceShape = new GeoTube(m_rmin, m_rmax, halflength);
229 } else if (m_shapeType == "TUBS") {
230 serviceShape = new GeoTubs(m_rmin, m_rmax, halflength, m_phiLoc, m_phiWidth);
231 } else if (m_shapeType == "CONS" || m_shapeType == "CONE") {
232 double phiWidthTmp = m_phiWidth;
233 if (m_shapeType == "CONE" || phiWidthTmp == 0) {
234 phiWidthTmp = 2 * M_PI;
235 }
236 serviceShape = new GeoCons(m_rmin, m_rmin2, m_rmax, m_rmax2, halflength, m_phiLoc, phiWidthTmp);
237 } else if (m_shapeType == "PGON") {
238 GeoPgon* shapeTmp = new GeoPgon(m_phiLoc, 2 * M_PI, m_sides);
239 shapeTmp->addPlane(-halflength, m_rmin, m_rmax);
240 shapeTmp->addPlane(halflength, m_rmin2, m_rmax2);
241 serviceShape = shapeTmp;
242 } else if (m_shapeType == "PGON2") {
243 // Radius defined at the side, not the corner
244 double alpha = M_PI / m_sides;
245 double cosalpha = cos(alpha);
246 double rminB = m_rmin / cosalpha;
247 double rmaxB = m_rmax / cosalpha;
248 double rmin2B = m_rmin2 / cosalpha;
249 double rmax2B = m_rmax2 / cosalpha;
250 GeoPgon* shapeTmp = new GeoPgon(m_phiLoc - alpha, 2 * M_PI, m_sides);
251 shapeTmp->addPlane(-halflength, rminB, rmaxB);
252 shapeTmp->addPlane(halflength, rmin2B, rmax2B);
253 serviceShape = shapeTmp;
254 } else if (m_shapeType == "PGON3" || m_shapeType == "PGON4") {
255 // Outer edge
256 GeoPgon* shapeTmp1 = nullptr;
257 if (m_shapeType == "PGON3") {
258 shapeTmp1 = new GeoPgon(m_phiLoc, 2 * M_PI, m_sides);
259 shapeTmp1->addPlane(-halflength, 0, m_rmax);
260 shapeTmp1->addPlane(halflength, 0, m_rmax2);
261 } else { //PGON4
262 double alpha = M_PI / m_sides;
263 double cosalpha = cos(alpha);
264 double rmaxB = m_rmax / cosalpha;
265 double rmax2B = m_rmax2 / cosalpha;
266 shapeTmp1 = new GeoPgon(m_phiLoc - alpha, 2 * M_PI, m_sides);
267 shapeTmp1->addPlane(-halflength, 0, rmaxB);
268 shapeTmp1->addPlane(halflength, 0, rmax2B);
269 }
270 // Don't trust boolean volume calculation.
271 volume = shapeTmp1->volume();
272 // Inner edge
273 GeoShape* shapeTmp2 = nullptr;
274 if (m_rmin == m_rmin2) {
275 shapeTmp2 = new GeoTube(0, m_rmin, halflength + 0.1 * Gaudi::Units::mm);
276 volume -= 2 * M_PI * m_rmin * m_rmin * halflength;
277 } else {
278 shapeTmp2 = new GeoCons(0, 0, m_rmin, m_rmin2, halflength + 0.1 * Gaudi::Units::mm, 0, 2 * M_PI);
279 volume -= 2 * M_PI * pow(0.5 * (m_rmin + m_rmin2), 2) * halflength;
280 }
281 serviceShape = &(shapeTmp1->subtract(*shapeTmp2));
282 }
283// else if (m_shapeType == "PGON31"){
284// // Outer edge
285// GeoTube *shapeTmp1 = new GeoTube(0,m_rmax,halflength);
286// halflength+=0.1*CLHEP::mm;
287// double alpha = M_PI/m_sides;
288// double cosalpha = cos(alpha);
289// double rmaxB = m_rmin/cosalpha;
290// double rmax2B = m_rmin2/cosalpha;
291// GeoPgon* shapeTmp2 = new GeoPgon(m_phiLoc-alpha,2*M_PI,m_sides);
292// shapeTmp2->addPlane(-halflength,0.,rmaxB);
293// shapeTmp2->addPlane(halflength,0.,rmax2B);
294// // Don't trust boolean volume calculation.
295// volume = shapeTmp1->volume() - shapeTmp2->volume();
296// serviceShape = &(shapeTmp1->subtract(*shapeTmp2));
297// }
298 else if (m_shapeType == "ROD") {
299 serviceShape = new GeoTube(0, 0.5 * m_phiWidth, halflength);
300 } else if (m_shapeType == "ROD2") {
301 // std::cout<<"ROD2 : "<<m_rmin<<" "<<m_rmin2<<" "<<0.5*m_phiWidth<<" "<<halflength<<std::endl;
302 serviceShape = new GeoTube(m_rmin2 - m_rmin, 0.5 * m_phiWidth, halflength);
303 } else if (m_shapeType == "BOX") {
304 serviceShape = new GeoBox(0.5 * (m_rmax - m_rmin), 0.5 * m_phiWidth, halflength);
305 } else if (m_shapeType == "TRAP") {
306 double thickness = 0.5 * (m_rmax - m_rmin);
307 double averad = 0.5 * (m_rmin + m_rmax);
308 double w1 = 0.5 * m_phiWidth * m_rmin / averad;
309 double w2 = 0.5 * m_phiWidth * m_rmax / averad;
310 serviceShape = new GeoTrap(halflength, 0, 0, thickness, w1, w2, 0, thickness, w1, w2, 0);
311 } else {
312 // msg(MSG::ERROR) << "Unrecognized shape for services" << m_shapeType << endmsg;
313 std::cout << "ServiceVolume: ERROR: Unrecognized shape for services" << m_shapeType << std::endl;
314 }
315
316 if (!volume && serviceShape != nullptr) volume = serviceShape->volume();
317
318 m_volume = volume;
319 m_geoShape = serviceShape;
320 return serviceShape;
321 }
322
323 double
325 // Make sure shape is already built.
326 getShape();
327 std::lock_guard<std::mutex> lock(m_mutex);
328 return m_volume;
329 }
330
331 void
332 ServiceVolume::setGeoShape(const GeoShape* geoShape, double volume) {
333 m_geoShape.reset();
334 if (geoShape) {
335 m_volume = volume;
336 // We allow a volume to specified as the volume calculation for some shapes (ie boolean volumes) are unreliable.
337 // If volume is not supplied, get it from the shape itself.
338 if (!m_volume) m_volume = geoShape->volume();
339 m_geoShape = geoShape;
340 m_lockGeoShape = true; // This disables resetGeoShape().
341 setShapeType("CUSTOM");
342 } else {
343 // If pass null pointer we unlock the shape.
344 m_lockGeoShape = false;
345 }
346 }
347
348 double
350 if (m_origVolume) return m_origVolume;
351
352 return volume();
353 }
354
355 void
358 if (m_shapeType == "CUSTOM") {
360 } else if (!(m_shapeType.empty() || m_shapeType == "TUBE" || m_shapeType == "TUBS")) {
361 m_splittableR = false;
362 }
363 }
364
365} // end namespace
#define M_PI
constexpr int pow(int base, int exp) noexcept
void setGeoShape(const GeoShape *geoShape, double volume=0)
void setLabel(const std::string &name, int volId)
Message Stream Member.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)