ATLAS Offline Software
Geo2G4SolidFactory.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "Geo2G4SolidFactory.h"
6 #include "LArWheelSolid.h"
7 #include "LArWheelSliceSolid.h"
8 #include "LArWheelSolidDDProxy.h"
9 
10 
11 #include "GeoModelKernel/GeoShape.h"
12 #include "GeoModelKernel/GeoBox.h"
13 #include "GeoModelKernel/GeoTube.h"
14 #include "GeoModelKernel/GeoTubs.h"
15 #include "GeoModelKernel/GeoTrd.h"
16 #include "GeoModelKernel/GeoPcon.h"
17 #include "GeoModelKernel/GeoPgon.h"
18 #include "GeoModelKernel/GeoPara.h"
19 #include "GeoModelKernel/GeoTrap.h"
20 #include "GeoModelKernel/GeoCons.h"
21 #include "GeoModelKernel/GeoSimplePolygonBrep.h"
22 #include "GeoModelKernel/GeoTessellatedSolid.h"
23 #include "GeoModelKernel/GeoEllipticalTube.h"
24 #include "GeoModelKernel/GeoTorus.h"
25 #include "GeoModelKernel/GeoGenericTrap.h"
26 #include "GeoModelKernel/GeoShapeShift.h"
27 #include "GeoModelKernel/GeoShapeUnion.h"
28 #include "GeoModelKernel/GeoShapeIntersection.h"
29 #include "GeoModelKernel/GeoUnidentifiedShape.h"
30 #include "GeoModelKernel/GeoShapeSubtraction.h"
31 
32 
33 #include "GaudiKernel/ISvcLocator.h"
34 #include "GaudiKernel/Bootstrap.h"
40 
41 
44 
45 
46 
47 #include "G4VSolid.hh"
48 #include "G4Box.hh"
49 #include "G4Tubs.hh"
50 #include "G4Trd.hh"
51 #include "G4Polycone.hh"
52 #include "G4Cons.hh"
53 #include "G4Polyhedra.hh"
54 #include "G4Trap.hh"
55 #include "G4Para.hh"
56 #include "G4UnionSolid.hh"
57 #include "G4DisplacedSolid.hh"
58 #include "G4IntersectionSolid.hh"
59 #include "G4SubtractionSolid.hh"
60 #include "G4ExtrudedSolid.hh"
61 #include "G4TessellatedSolid.hh"
62 #include "G4EllipticalTube.hh"
63 #include "G4Torus.hh"
64 #include "G4TriangularFacet.hh"
65 #include "G4QuadrangularFacet.hh"
66 #include "G4GenericTrap.hh"
67 
68 #include <iostream>
69 #include <map>
70 #include <cmath>
71 #include <utility>
72 
74 
75 typedef std::map<const GeoShape*, G4VSolid*, std::less<const GeoShape*> > shapesMap;
76 typedef std::map<std::string, G4VSolid*,std::less<std::string> > customSolidMap;
77 
79 /* entries w/o explicit Pos/Neg kept for backward compatibility */
80  { "LAr::EMEC::InnerWheel::Absorber", {InnerAbsorberWheel, 1} },
81  { "LAr::EMEC::InnerWheel::Electrode", {InnerElectrodWheel, 1} },
82  { "LAr::EMEC::InnerWheel::Glue", {InnerGlueWheel, 1} },
83  { "LAr::EMEC::InnerWheel::Lead", {InnerLeadWheel, 1} },
84 
85  { "LAr::EMEC::OuterWheel::Absorber", {OuterAbsorberWheel, 1} },
86  { "LAr::EMEC::OuterWheel::Electrode", {OuterElectrodWheel, 1} },
87  { "LAr::EMEC::OuterWheel::Glue", {OuterGlueWheel, 1} },
88  { "LAr::EMEC::OuterWheel::Lead", {OuterLeadWheel, 1} },
89 
90  { "LAr::EMEC::Pos::InnerWheel::Absorber", {InnerAbsorberWheel, 1} },
91  { "LAr::EMEC::Pos::InnerWheel::Electrode", {InnerElectrodWheel, 1} },
92  { "LAr::EMEC::Pos::InnerWheel::Glue", {InnerGlueWheel, 1} },
93  { "LAr::EMEC::Pos::InnerWheel::Lead", {InnerLeadWheel, 1} },
94 
95  { "LAr::EMEC::Pos::OuterWheel::Absorber", {OuterAbsorberWheel, 1} },
96  { "LAr::EMEC::Pos::OuterWheel::Electrode", {OuterElectrodWheel, 1} },
97  { "LAr::EMEC::Pos::OuterWheel::Glue", {OuterGlueWheel, 1} },
98  { "LAr::EMEC::Pos::OuterWheel::Lead", {OuterLeadWheel, 1} },
99 
100  { "LAr::EMEC::Neg::InnerWheel::Absorber", {InnerAbsorberWheel, -1} },
101  { "LAr::EMEC::Neg::InnerWheel::Electrode", {InnerElectrodWheel, -1} },
102  { "LAr::EMEC::Neg::InnerWheel::Glue", {InnerGlueWheel, -1} },
103  { "LAr::EMEC::Neg::InnerWheel::Lead", {InnerLeadWheel, -1} },
104 
105  { "LAr::EMEC::Neg::OuterWheel::Absorber", {OuterAbsorberWheel, -1} },
106  { "LAr::EMEC::Neg::OuterWheel::Electrode", {OuterElectrodWheel, -1} },
107  { "LAr::EMEC::Neg::OuterWheel::Glue", {OuterGlueWheel, -1} },
108  { "LAr::EMEC::Neg::OuterWheel::Lead", {OuterLeadWheel, -1} },
109 
110  { "LAr::EMEC::InnerModule::Absorber", {InnerAbsorberModule, 1} },
111  { "LAr::EMEC::InnerModule::Electrode", {InnerElectrodModule, 1} },
112  { "LAr::EMEC::OuterModule::Absorber", {OuterAbsorberModule, 1} },
113  { "LAr::EMEC::OuterModule::Electrode", {OuterElectrodModule, 1} },
114 
115  { "LAr::EMEC::Pos::InnerCone::Absorber", {InnerAbsorberCone, 1} },
116  { "LAr::EMEC::Pos::InnerCone::Electrode", {InnerElectrodCone, 1} },
117  { "LAr::EMEC::Pos::InnerCone::Glue", {InnerGlueCone, 1} },
118  { "LAr::EMEC::Pos::InnerCone::Lead", {InnerLeadCone, 1} },
119 
120  { "LAr::EMEC::Neg::InnerCone::Absorber", {InnerAbsorberCone, -1} },
121  { "LAr::EMEC::Neg::InnerCone::Electrode", {InnerElectrodCone, -1} },
122  { "LAr::EMEC::Neg::InnerCone::Glue", {InnerGlueCone, -1} },
123  { "LAr::EMEC::Neg::InnerCone::Lead", {InnerLeadCone, -1} },
124 
125  { "LAr::EMEC::Pos::OuterFrontCone::Absorber", {OuterAbsorberFrontCone, 1} },
126  { "LAr::EMEC::Pos::OuterFrontCone::Electrode", {OuterElectrodFrontCone, 1} },
127  { "LAr::EMEC::Pos::OuterFrontCone::Glue", {OuterGlueFrontCone, 1} },
128  { "LAr::EMEC::Pos::OuterFrontCone::Lead", {OuterLeadFrontCone, 1} },
129 
130  { "LAr::EMEC::Neg::OuterFrontCone::Absorber", {OuterAbsorberFrontCone, -1} },
131  { "LAr::EMEC::Neg::OuterFrontCone::Electrode", {OuterElectrodFrontCone, -1} },
132  { "LAr::EMEC::Neg::OuterFrontCone::Glue", {OuterGlueFrontCone, -1} },
133  { "LAr::EMEC::Neg::OuterFrontCone::Lead", {OuterLeadFrontCone, -1} },
134 
135  { "LAr::EMEC::Pos::OuterBackCone::Absorber", {OuterAbsorberBackCone, 1} },
136  { "LAr::EMEC::Pos::OuterBackCone::Electrode", {OuterElectrodBackCone, 1} },
137  { "LAr::EMEC::Pos::OuterBackCone::Glue", {OuterGlueBackCone, 1} },
138  { "LAr::EMEC::Pos::OuterBackCone::Lead", {OuterLeadBackCone, 1} },
139 
140  { "LAr::EMEC::Neg::OuterBackCone::Absorber", {OuterAbsorberBackCone, -1} },
141  { "LAr::EMEC::Neg::OuterBackCone::Electrode", {OuterElectrodBackCone, -1} },
142  { "LAr::EMEC::Neg::OuterBackCone::Glue", {OuterGlueBackCone, -1} },
143  { "LAr::EMEC::Neg::OuterBackCone::Lead", {OuterLeadBackCone, -1} },
144 };
145 
147  AthMessaging("Geo2G4SolidFactory"),
148  m_detStore( "StoreGateSvc/DetectorStore", "Geo2G4SolidFactory" )
149 {
150 }
151 
152 G4VSolid *Geo2G4SolidFactory::Build ATLAS_NOT_THREAD_SAFE (const GeoShape* geoShape, std::string name)
153 {
154  G4VSolid* theSolid(nullptr);
155 
156  static customSolidMap customSolids;
157  static shapesMap sharedShapes;
158  if(sharedShapes.find(geoShape)!=sharedShapes.end())
159  return sharedShapes[geoShape];
160 
161  // ------- Variables for boolean operations
162  G4VSolid* solidA(nullptr);
163  G4VSolid* solidB(nullptr);
164  // ------- Variables for Pcon and Pgon
165  int nPlanes;
166 
167  std::string n = std::move(name);
168 
169  //
170  // The Box
171  //
172  if(geoShape->typeID() == GeoBox::getClassTypeID() )
173  {
174  const GeoBox* theBox = dynamic_cast<const GeoBox*> (geoShape);
175  if (nullptr==theBox) throw std::runtime_error("TypeID did not match cast for box");
176  if (n.empty()) n="G4Box";
177  if (theBox->getXHalfLength()<=0.){ ATH_MSG_WARNING("Box " << n << " has an x side of " << theBox->getXHalfLength() <<" - using std::abs.");}
178  if (theBox->getYHalfLength()<=0.){ ATH_MSG_WARNING("Box " << n << " has an y side of " << theBox->getYHalfLength() <<" - using std::abs.");}
179  if (theBox->getZHalfLength()<=0.){ ATH_MSG_WARNING("Box " << n << " has an z side of " << theBox->getZHalfLength() <<" - using std::abs.");}
180  theSolid = new G4Box(n,
181  std::abs(theBox->getXHalfLength()),
182  std::abs(theBox->getYHalfLength()),
183  std::abs(theBox->getZHalfLength()));
184  }
185  //
186  // The Tube
187  //
188  else if(geoShape->typeID() == GeoTube::getClassTypeID() )
189  {
190  const GeoTube* theTube = dynamic_cast<const GeoTube*> (geoShape);
191  if (nullptr==theTube) throw std::runtime_error("TypeID did not match cast for tube");
192  if (n.empty()) n="G4Tube";
193  if (theTube->getRMax()<=0.){ ATH_MSG_WARNING("Tube " << n << " has a max radius of " << theTube->getRMax() <<" - using std::abs.");}
194  if (theTube->getZHalfLength()<=0.){ ATH_MSG_WARNING("Tube " << n << " has a z half length of " << theTube->getZHalfLength() << " - using std::abs.");}
195  if (theTube->getRMax()<theTube->getRMin()){ ATH_MSG_WARNING("Tube " << n << " has a max radius of " << theTube->getRMax() << " and a min radius of " << theTube->getRMin());}
196  theSolid = new G4Tubs(n,
197  theTube->getRMin(),
198  std::abs(theTube->getRMax()),
199  std::abs(theTube->getZHalfLength()),
200  0.,360*CLHEP::deg);
201  }
202  //
203  // The Tubs
204  //
205  else if(geoShape->typeID() == GeoTubs::getClassTypeID() )
206  {
207  const GeoTubs* theTubs = dynamic_cast<const GeoTubs*> (geoShape);
208  if (nullptr==theTubs) throw std::runtime_error("TypeID did not match cast for tubs");
209  if (n.empty()) n="G4Tubs";
210  if (theTubs->getRMin()<0.){ ATH_MSG_WARNING("Tubs " << n << " has a min radius of " << theTubs->getRMax());}
211  if (theTubs->getRMax()<=0.){ ATH_MSG_WARNING("Tubs " << n << " has a max radius of " << theTubs->getRMax() <<" - using std::abs.");}
212  if (theTubs->getZHalfLength()<=0.){ ATH_MSG_WARNING("Tubs " << n << " has a half length of " << theTubs->getZHalfLength() <<" - using std::abs.");}
213  if (theTubs->getRMax()<theTubs->getRMin()){ ATH_MSG_WARNING("Tubs " << n << " has a max radius of " << theTubs->getRMax() << " and a min radius of " << theTubs->getRMin());}
214  if (theTubs->getDPhi()<=0.){ ATH_MSG_WARNING("Tubs " << n << " has a dPhi of " << theTubs->getDPhi());}
215  theSolid = new G4Tubs(n,
216  theTubs->getRMin(),
217  std::abs(theTubs->getRMax()),
218  std::abs(theTubs->getZHalfLength()),
219  theTubs->getSPhi(),
220  theTubs->getDPhi());
221  }
222  //
223  // The Trd
224  //
225  else if(geoShape->typeID() == GeoTrd::getClassTypeID() )
226  {
227  const GeoTrd* theTrd = dynamic_cast<const GeoTrd*> (geoShape);
228  if (nullptr==theTrd) throw std::runtime_error("TypeID did not match cast for trd");
229  if (n.empty()) n="G4Trd";
230  if (theTrd->getXHalfLength1()<0.){ ATH_MSG_WARNING("Trd " << n << " has a x half length 1 of " << theTrd->getXHalfLength1() << " - using std::abs.");}
231  if (theTrd->getXHalfLength2()<0.){ ATH_MSG_WARNING("Trd " << n << " has a x half length 2 of " << theTrd->getXHalfLength2() << " - using std::abs.");}
232  if (theTrd->getYHalfLength1()<0.){ ATH_MSG_WARNING("Trd " << n << " has a y half length 1 of " << theTrd->getYHalfLength1() << " - using std::abs.");}
233  if (theTrd->getYHalfLength2()<0.){ ATH_MSG_WARNING("Trd " << n << " has a y half length 2 of " << theTrd->getYHalfLength2() << " - using std::abs.");}
234  if (theTrd->getZHalfLength()<=0.){ ATH_MSG_WARNING("Trd " << n << " has a z half length of " << theTrd->getZHalfLength() << " - using std::abs.");}
235  if (theTrd->getXHalfLength1()<=0. && theTrd->getXHalfLength2()<=0.){ ATH_MSG_WARNING("Trd " << n << " has an x half length 1 of " << theTrd->getXHalfLength1()
236  << " and an x half length 2 of " << theTrd->getXHalfLength2() << " - using std::abs.");}
237  if (theTrd->getYHalfLength1()<=0. && theTrd->getYHalfLength2()<=0.){ ATH_MSG_WARNING("Trd " << n << " has a y half length 1 of " << theTrd->getYHalfLength1()
238  << " and a y half length 2 of " << theTrd->getYHalfLength2() << " - using std::abs.");}
239  theSolid = new G4Trd(n,
240  std::abs(theTrd->getXHalfLength1()),
241  std::abs(theTrd->getXHalfLength2()),
242  std::abs(theTrd->getYHalfLength1()),
243  std::abs(theTrd->getYHalfLength2()),
244  std::abs(theTrd->getZHalfLength()));
245  }
246  //
247  // GeoPcon
248  //
249  else if(geoShape->typeID() == GeoPcon::getClassTypeID())
250  {
251  const GeoPcon* thePcon = dynamic_cast<const GeoPcon*>(geoShape);
252  if (nullptr==thePcon) throw std::runtime_error("TypeID did not match cast for pcon");
253  if (n.empty()) n="G4Polycone";
254  nPlanes = static_cast<int>(thePcon->getNPlanes());
255  // NB G4Polycone copies the contents of these arrays rather than taking ownership.
256  auto zPlane = std::make_unique<double[]>(nPlanes);
257  auto rInner = std::make_unique<double[]>(nPlanes);
258  auto rOuter = std::make_unique<double[]>(nPlanes);
259  for (unsigned int index=0; index<static_cast<unsigned int>(nPlanes); index++)
260  {
261  zPlane[index] = thePcon->getZPlane(index);
262  rInner[index] = thePcon->getRMinPlane(index);
263  rOuter[index] = thePcon->getRMaxPlane(index);
264  if (rInner[index]<0.){ ATH_MSG_WARNING("PCon " << n << " has an inner radius of " << rInner[index] << " for slice " << index << " of " << nPlanes);}
265  if (rOuter[index]<=0.){
266  ATH_MSG_WARNING("PCon " << n << " has an outer radius of " << rOuter[index] << " for slice " << index << " of " << nPlanes << " - using std::abs.");
267  rOuter[index] = std::abs(rOuter[index]);
268  }
269  }
270 
271  theSolid = new G4Polycone(n,
272  thePcon->getSPhi(),
273  thePcon->getDPhi(),
274  nPlanes,
275  zPlane.get(),
276  rInner.get(),
277  rOuter.get());
278  }
279  //
280  // GeoCons
281  //
282  else if(geoShape->typeID() == GeoCons::getClassTypeID())
283  {
284  const GeoCons* theCons = dynamic_cast<const GeoCons*>(geoShape);
285  if (nullptr==theCons) throw std::runtime_error("TypeID did not match cast for cons");
286  if (n.empty()) n="G4Cons";
287  if (theCons->getRMax1()<0.){ ATH_MSG_WARNING("Cons " << n << " has a max radius 1 of " << theCons->getRMax1() << " - will use std::abs.");}
288  if (theCons->getRMax2()<0.){ ATH_MSG_WARNING("Cons " << n << " has a max radius 2 of " << theCons->getRMax2() << " - will use std::abs.");}
289  if (theCons->getRMin1()<0.){ ATH_MSG_WARNING("Cons " << n << " has a min radius 1 of " << theCons->getRMin1());}
290  if (theCons->getRMin2()<0.){ ATH_MSG_WARNING("Cons " << n << " has a min radius 2 of " << theCons->getRMin2());}
291  if (theCons->getDZ()<=0){ ATH_MSG_WARNING("Cons " << n << " has a DZ of " << theCons->getDZ() << " - will use std::abs.");}
292  if (theCons->getRMax1()<=0. && theCons->getRMax2()<=0.){ ATH_MSG_WARNING("Cons " << n << " has a max radius 1 of " << theCons->getRMax1()
293  << " and a max radius 2 of " << theCons->getRMax2() << " - will use std::abs.");}
294  theSolid = new G4Cons(n,
295  theCons->getRMin1(),
296  std::abs(theCons->getRMax1()),
297  theCons->getRMin2(),
298  std::abs(theCons->getRMax2()),
299  std::abs(theCons->getDZ()),
300  theCons->getSPhi(),
301  theCons->getDPhi());
302  }
303  //
304  // GeoPara
305  //
306  else if(geoShape->typeID() == GeoPara::getClassTypeID())
307  {
308  const GeoPara* thePara = dynamic_cast<const GeoPara*>(geoShape);
309  if (nullptr==thePara) throw std::runtime_error("TypeID did not match cast for para");
310  if (n.empty()) n="G4Para";
311  if (thePara->getXHalfLength()<=0.){ ATH_MSG_WARNING("Para " << n << " has an x side of " << thePara->getXHalfLength() <<" - using std::abs.");}
312  if (thePara->getYHalfLength()<=0.){ ATH_MSG_WARNING("Para " << n << " has an y side of " << thePara->getYHalfLength() <<" - using std::abs.");}
313  if (thePara->getZHalfLength()<=0.){ ATH_MSG_WARNING("Para " << n << " has an z side of " << thePara->getZHalfLength() <<" - using std::abs.");}
314  theSolid = new G4Para(n,
315  std::abs(thePara->getXHalfLength()),
316  std::abs(thePara->getYHalfLength()),
317  std::abs(thePara->getZHalfLength()),
318  thePara->getAlpha(),
319  thePara->getTheta(),
320  thePara->getPhi());
321  }
322  //
323  // GeoPgon
324  //
325  else if(geoShape->typeID() == GeoPgon::getClassTypeID())
326  {
327  const GeoPgon* thePgon = dynamic_cast<const GeoPgon*>(geoShape);
328  if (nullptr==thePgon) throw std::runtime_error("TypeID did not match cast for pgon");
329  if (n.empty()) n="G4Polyhedra";
330  nPlanes = static_cast<int>(thePgon->getNPlanes());
331  // NB G4Polyhedra copies the contents of these arrays rather than taking ownership.
332  auto zPlane = std::make_unique<double[]>(nPlanes);
333  auto rInner = std::make_unique<double[]>(nPlanes);
334  auto rOuter = std::make_unique<double[]>(nPlanes);
335  double alpha = thePgon->getDPhi()/(2*thePgon->getNSides()); // 1/2 openning angle
336  for (unsigned int index=0; index<static_cast<unsigned int>(nPlanes); index++)
337  {
338  zPlane[index] = thePgon->getZPlane(index);
339  rInner[index] = thePgon->getRMinPlane(index)*cos(alpha);
340  rOuter[index] = thePgon->getRMaxPlane(index)*cos(alpha);
341  if (rInner[index]<0.){ ATH_MSG_WARNING("Pgon " << n << " has an inner radius of " << rInner[index] << " for slice " << index << " of " << nPlanes);}
342  if (rOuter[index]<=0.){
343  ATH_MSG_WARNING("Pgon " << n << " has an outer radius of " << rOuter[index] << " for slice " << index << " of " << nPlanes << " - using std::abs.");
344  rOuter[index] = std::abs(rOuter[index]);
345  }
346  }
347 
348  theSolid = new G4Polyhedra(n,
349  thePgon->getSPhi(),
350  thePgon->getDPhi(),
351  thePgon->getNSides(),
352  nPlanes,
353  zPlane.get(),
354  rInner.get(),
355  rOuter.get());
356  }
357  //
358  // GeoTrap
359  //
360  else if(geoShape->typeID() == GeoTrap::getClassTypeID())
361  {
362  const GeoTrap* theTrap = dynamic_cast<const GeoTrap*>(geoShape);
363  if (nullptr==theTrap) throw std::runtime_error("TypeID did not match cast for trap");
364  if (n.empty()) n="G4Trap";
365  if (theTrap->getZHalfLength()<=0.){ ATH_MSG_WARNING("Trap " << n << " has an z side of " << theTrap->getZHalfLength() <<" - using std::abs.");}
366  theSolid = new G4Trap(n,
367  std::abs(theTrap->getZHalfLength()),
368  theTrap->getTheta(),
369  theTrap->getPhi(),
370  theTrap->getDydzn(),
371  theTrap->getDxdyndzn(),
372  theTrap->getDxdypdzn(),
373  theTrap->getAngleydzn(),
374  theTrap->getDydzp(),
375  theTrap->getDxdyndzp(),
376  theTrap->getDxdypdzp(),
377  theTrap->getAngleydzp());
378  }
379  //
380  // Simple Polygon Brep
381  //
382  else if(geoShape->typeID() == GeoSimplePolygonBrep::getClassTypeID())
383  {
384  const GeoSimplePolygonBrep* theBrep = dynamic_cast<const GeoSimplePolygonBrep*>(geoShape);
385  if (nullptr==theBrep) throw std::runtime_error("TypeID did not match cast for brep");
386  if (n.empty()) n="G4ExtrudedSolid";
387  double dz = theBrep->getDZ();
388  int nVertices = theBrep->getNVertices();
389 
390  G4TwoVector off(0,0);
391  std::vector<G4TwoVector> polygon;
392 
393  polygon.reserve(nVertices);
394 for(int i=0; i<nVertices; i++)
395  polygon.push_back(G4TwoVector(theBrep->getXVertex(nVertices-1-i),theBrep->getYVertex(nVertices-1-i)));
396 
397  theSolid = new G4ExtrudedSolid(n,polygon,dz,off,1,off,1);
398  }
399  //
400  // Tessellated Solid
401  //
402  else if(geoShape->typeID() == GeoTessellatedSolid::getClassTypeID())
403  {
404  const GeoTessellatedSolid* theTessellated = dynamic_cast<const GeoTessellatedSolid*>(geoShape);
405  if (nullptr==theTessellated) throw std::runtime_error("TypeID did not match cast for tessellated solid");
406  if(n.empty()) n="G4TessellatedSolid";
407 
408  G4TessellatedSolid* g4Tessellated = new G4TessellatedSolid(n);
409  for(size_t i=0; i<theTessellated->getNumberOfFacets(); ++i) {
410  GeoFacet* geoFacet = theTessellated->getFacet(i);
411  G4FacetVertexType vertexType = (geoFacet->getVertexType()==GeoFacet::ABSOLUTE? ABSOLUTE : RELATIVE);
412  G4VFacet* g4Facet(nullptr);
413  if(geoFacet->getNumberOfVertices()==3)
414  g4Facet = new G4TriangularFacet(Amg::EigenToHep3Vector(geoFacet->getVertex(0)),
415  Amg::EigenToHep3Vector(geoFacet->getVertex(1)),
416  Amg::EigenToHep3Vector(geoFacet->getVertex(2)),
417  vertexType);
418  else
419  g4Facet = new G4QuadrangularFacet(Amg::EigenToHep3Vector(geoFacet->getVertex(0)),
420  Amg::EigenToHep3Vector(geoFacet->getVertex(1)),
421  Amg::EigenToHep3Vector(geoFacet->getVertex(2)),
422  Amg::EigenToHep3Vector(geoFacet->getVertex(3)),
423  vertexType);
424 
425  g4Tessellated->AddFacet(g4Facet);
426  }
427  g4Tessellated->SetSolidClosed(true);
428  theSolid = g4Tessellated;
429  }
430  //
431  // Elliptical Tube
432  //
433  else if(geoShape->typeID() == GeoEllipticalTube::getClassTypeID())
434  {
435  const GeoEllipticalTube* theEltube = dynamic_cast<const GeoEllipticalTube*>(geoShape);
436  if (nullptr==theEltube) throw std::runtime_error("TypeID did not match cast for elliptical tube");
437  if (n.empty()) n="G4EllipticalTube";
438 
439  if (theEltube->getXHalfLength()<=0.){ ATH_MSG_WARNING("Eltube " << n << " has an x side of " << theEltube->getXHalfLength() <<" - using std::abs.");}
440  if (theEltube->getYHalfLength()<=0.){ ATH_MSG_WARNING("Eltube " << n << " has an y side of " << theEltube->getYHalfLength() <<" - using std::abs.");}
441  if (theEltube->getZHalfLength()<=0.){ ATH_MSG_WARNING("Eltube " << n << " has an z side of " << theEltube->getZHalfLength() <<" - using std::abs.");}
442  G4EllipticalTube* g4Eltube = new G4EllipticalTube(n
443  ,std::abs(theEltube->getXHalfLength())
444  ,std::abs(theEltube->getYHalfLength())
445  ,std::abs(theEltube->getZHalfLength()));
446  theSolid = g4Eltube;
447  }
448  //
449  // Torus
450  //
451  else if(geoShape->typeID() == GeoTorus::getClassTypeID() ) {
452  const GeoTorus* theTorus = dynamic_cast<const GeoTorus*> (geoShape);
453  if (nullptr==theTorus) throw std::runtime_error("TypeID did not match cast for torus");
454  if (n.empty()) n="G4Torus";
455 
456  theSolid = new G4Torus(n,
457  theTorus->getRMin(),
458  theTorus->getRMax(),
459  theTorus->getRTor(),
460  theTorus->getSPhi(),
461  theTorus->getDPhi());
462  }
463  //
464  // Generic Trap
465  //
466  else if(geoShape->typeID() == GeoGenericTrap::getClassTypeID()) {
467  const GeoGenericTrap* theGenTrap = dynamic_cast<const GeoGenericTrap*>(geoShape);
468  if (nullptr==theGenTrap) throw std::runtime_error("TypeID did not match cast for generic trap");
469  if (n.empty()) n="G4GenericTrap";
470  if (theGenTrap->getZHalfLength()<=0.){ ATH_MSG_WARNING("GenTrap " << n << " has an z side of " << theGenTrap->getZHalfLength() <<" - using std::abs.");}
471 
472  // Translate vector of vertices from Eigen to CLHEP
473  std::vector<CLHEP::Hep2Vector> clhepVertices;
474  clhepVertices.reserve(theGenTrap->getVertices().size());
475  for(const GeoTrf::Vector2D& geoVertex : theGenTrap->getVertices()) {
476  clhepVertices.push_back(CLHEP::Hep2Vector(geoVertex.x(),geoVertex.y()));
477  }
478 
479  G4GenericTrap* g4GenTrap = new G4GenericTrap(n
480  ,std::abs(theGenTrap->getZHalfLength())
481  ,clhepVertices);
482  theSolid = g4GenTrap;
483  }
484  //
485  // Boolean volumes
486  // We make use of G4DisplacedSolid which is not documented in the manual but makes the implementation
487  // a lot simpler.
488  //
489  // GeoShapeShift
490  //
491  else if (geoShape->typeID() == GeoShapeShift::getClassTypeID() )
492  {
493  const GeoShapeShift* theShapeShift = dynamic_cast<const GeoShapeShift*> (geoShape);
494  if (nullptr==theShapeShift) throw std::runtime_error("TypeID did not match cast for shape shift");
495  if (n.empty()) n="DisplacedSolid";
496  G4VSolid * undisplacedSolid = Build(theShapeShift->getOp());
497  theSolid = new G4DisplacedSolid(n, undisplacedSolid, Amg::EigenTransformToCLHEP(theShapeShift->getX()));
498  }
499  //
500  // GeoShapeUnion
501  //
502  else if (geoShape->typeID() == GeoShapeUnion::getClassTypeID() )
503  {
504  const GeoShapeUnion* theUnion = dynamic_cast<const GeoShapeUnion*> (geoShape);
505  if (nullptr==theUnion) throw std::runtime_error("TypeID did not match cast for union");
506  if (n.empty()) n="Union";
507  solidA = Build(theUnion->getOpA());
508  solidB = Build(theUnion->getOpB());
509  theSolid = new G4UnionSolid(n, solidA, solidB);
510  }
511  //
512  // GeoShapeIntersection
513  //
514  else if (geoShape->typeID() == GeoShapeIntersection::getClassTypeID() )
515  {
516  const GeoShapeIntersection* theIntersection = dynamic_cast<const GeoShapeIntersection*>(geoShape);
517  if (nullptr==theIntersection) throw std::runtime_error("TypeID did not match cast for intersection");
518  if (n.empty()) n="Intersection";
519  solidA = Build(theIntersection->getOpA());
520  solidB = Build(theIntersection->getOpB());
521  theSolid = new G4IntersectionSolid(n, solidA, solidB);
522  }
523  //
524  // GeoShapeSubtraction
525  //
526  else if (geoShape->typeID() == GeoShapeSubtraction::getClassTypeID() )
527  {
528  const GeoShapeSubtraction* theSubtraction = dynamic_cast<const GeoShapeSubtraction*>(geoShape);
529  if (nullptr==theSubtraction) throw std::runtime_error("TypeID did not match cast for subtraction");
530  if (n.empty()) n="Subtraction";
531  solidA = Build(theSubtraction->getOpA());
532  solidB = Build(theSubtraction->getOpB());
533  theSolid = new G4SubtractionSolid(n, solidA, solidB);
534  }
535  //
536  // Custom Shapes (presently LAr shapes only)
537  //
538  else if(geoShape->typeID() == GeoUnidentifiedShape::getClassTypeID())
539  {
540  const GeoUnidentifiedShape* customShape = dynamic_cast<const GeoUnidentifiedShape*> (geoShape);
541  if (nullptr==customShape) throw std::runtime_error("TypeID did not match cast for custom shape");
542  if (customShape->name()=="LArCustomShape") {
543 
544 
545 
546  ISvcLocator* svcLocator = Gaudi::svcLocator();
547  // Access the GeoModelSvc:
548  SmartIF<IGeoModelSvc> geoModel{svcLocator->service ("GeoModelSvc")};
549  if ( !geoModel ) {
550  G4Exception(
551  "Geo2G4SolidFactory", "AccessGeoModel", FatalException,
552  "Build cannot access GeoModelSvc");
553  }
554  SmartIF<IGeoDbTagSvc> geoDbTagSvc{svcLocator->service ("GeoDbTagSvc")};
555  if ( !geoDbTagSvc ) {
556  G4Exception(
557  "Geo2G4SolidFactory", "AccessDbTagSvc", FatalException,
558  "Build cannot access DbTagSvc");
559  }
560  // Access the geometry database:
561  SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service(geoDbTagSvc->getParamSvcName())};
562  if ( !pAccessSvc ) {
563  G4Exception(
564  "Geo2G4SolidFactory", "AccessAccessSvc", FatalException,
565  "Build cannot access AccessSvc");
566  }
567  DecodeVersionKey larVersionKey(geoModel, "LAr");
568  EMECData emecData=toEMECData(pAccessSvc,larVersionKey);
569 
570 
571 
572  std::string customName = customShape->asciiData();
573  customSolidMap::const_iterator it = customSolids.find(customName);
574  if(it!=customSolids.end())
575  theSolid = it->second;
576  else
577  {
578  theSolid = nullptr;
579  if(customName.find("Slice") != std::string::npos){
580  theSolid = createLArWheelSliceSolid(customShape,emecData);
581  } else {
582  theSolid = createLArWheelSolid(customName, s_lwsTypes.at(customName) ,emecData); // map.at throws std::out_of_range exception on unknown shape name
583  }
584  if ( nullptr == theSolid ) {
585  std::string error = std::string("Can't create LArWheelSolid for name ") + customName + " in Geo2G4SolidFactory::Build";
586  throw std::runtime_error(error);
587  }
588 
589  if(theSolid != nullptr) customSolids[customName] = theSolid;
590  }
591  }
592  }
593  //
594  // Catch All
595  //
596  else
597  {
598  ATH_MSG_FATAL("Sorry this solid is not yet implemented... ");
599  ATH_MSG_FATAL(geoShape->type());
600  ATH_MSG_FATAL("You will have a core dump...");
601  return nullptr;
602  }
603 
604  sharedShapes[geoShape] = theSolid;
605  return theSolid;
606 }
607 
608 G4VSolid* Geo2G4SolidFactory::createLArWheelSolid ATLAS_NOT_THREAD_SAFE (const std::string& name, const LArWheelSolidDef_t & lwsdef, const EMECData & emecData) const { // LArWheelSolid_t wheelType, int zside
609  LArWheelSolid_t wheelType = lwsdef.first;
610  int zside = lwsdef.second;
611 
612  LArWheelSolid * theLWS = new LArWheelSolid(name, wheelType, zside,nullptr, &emecData);
613 
614  LArWheelSolidDDProxy * theLWS_p = new LArWheelSolidDDProxy(theLWS);
615  // ownership is passed to detStore
616  if ( m_detStore->record(theLWS_p, name).isFailure() ) {
617  ATH_MSG_WARNING("Can't store proxy for LArWheelSolid to the DetectorStore");
618  delete theLWS_p;
619  }
620  return theLWS;
621 }
622 
623 G4VSolid* Geo2G4SolidFactory::createLArWheelSliceSolid ATLAS_NOT_THREAD_SAFE (const GeoUnidentifiedShape* customShape, const EMECData & emecData) const
624 {
625  LArWheelSliceSolid *theLWS = new LArWheelSliceSolid(customShape->asciiData(),&emecData);
626 
627  LArWheelSolidDDProxy *theLWS_p = new LArWheelSolidDDProxy(theLWS);
628  // ownership is passed to detStore
629  if(m_detStore->record(theLWS_p, theLWS->GetName()).isFailure()){
630  ATH_MSG_WARNING("Can't store proxy for LArWheelSolid to the DetectorStore");
631  delete theLWS_p;
632  }
633  return theLWS;
634 }
Geo2G4SolidFactory::s_lwsTypes
static const LArWheelSolid_typemap s_lwsTypes
Definition: Geo2G4SolidFactory.h:36
InnerElectrodCone
@ InnerElectrodCone
Definition: LArWheelSolid_type.h:26
InnerGlueWheel
@ InnerGlueWheel
Definition: LArWheelSolid_type.h:21
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
OuterLeadFrontCone
@ OuterLeadFrontCone
Definition: LArWheelSolid_type.h:32
NSWL1::nVertices
int nVertices(const Polygon &p)
Definition: GeoUtils.cxx:35
ATLAS_NOT_THREAD_SAFE
G4VSolid *Geo2G4SolidFactory::Build ATLAS_NOT_THREAD_SAFE(const GeoShape *geoShape, std::string name)
Definition: Geo2G4SolidFactory.cxx:152
Geo2G4SolidFactory::LArWheelSolid_typemap
std::map< std::string, LArWheelSolidDef_t > LArWheelSolid_typemap
Definition: Geo2G4SolidFactory.h:27
OuterAbsorberBackCone
@ OuterAbsorberBackCone
Definition: LArWheelSolid_type.h:33
LArWheelSliceSolid.h
EMECData.h
OuterLeadBackCone
@ OuterLeadBackCone
Definition: LArWheelSolid_type.h:36
OuterGlueWheel
@ OuterGlueWheel
Definition: LArWheelSolid_type.h:22
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
index
Definition: index.py:1
EMECData
Definition: EMECData.h:131
skel.it
it
Definition: skel.GENtoEVGEN.py:396
LArWheelSolid_t
LArWheelSolid_t
Definition: LArWheelSolid_type.h:12
deg
#define deg
Definition: SbPolyhedron.cxx:17
Amg::EigenToHep3Vector
CLHEP::Hep3Vector EigenToHep3Vector(const Amg::Vector3D &eigenvector)
Converts an Eigen-based Amg::Vector3D into a CLHEP-based CLHEP::Hep3Vector.
Definition: CLHEPtoEigenConverter.h:147
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
InnerElectrodModule
@ InnerElectrodModule
Definition: LArWheelSolid_type.h:19
Geo2G4SolidFactory::Geo2G4SolidFactory
Geo2G4SolidFactory()
Definition: Geo2G4SolidFactory.cxx:146
InnerElectrodWheel
@ InnerElectrodWheel
Definition: LArWheelSolid_type.h:15
InnerGlueCone
@ InnerGlueCone
Definition: LArWheelSolid_type.h:27
OuterElectrodModule
@ OuterElectrodModule
Definition: LArWheelSolid_type.h:20
OuterGlueFrontCone
@ OuterGlueFrontCone
Definition: LArWheelSolid_type.h:31
OuterAbsorberModule
@ OuterAbsorberModule
Definition: LArWheelSolid_type.h:18
LArWheelSolid.h
InnerLeadWheel
@ InnerLeadWheel
Definition: LArWheelSolid_type.h:23
OuterElectrodFrontCone
@ OuterElectrodFrontCone
Definition: LArWheelSolid_type.h:30
IRDBAccessSvc.h
Definition of the abstract IRDBAccessSvc interface.
lumiFormat.i
int i
Definition: lumiFormat.py:85
beamspotman.n
n
Definition: beamspotman.py:731
DecodeVersionKey
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
Definition: DecodeVersionKey.h:18
InnerAbsorberWheel
@ InnerAbsorberWheel
Definition: LArWheelSolid_type.h:13
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
shapesMap
std::map< const GeoShape *, G4VSolid *, std::less< const GeoShape * > > shapesMap
Definition: Geo2G4SolidFactory.cxx:75
OuterLeadWheel
@ OuterLeadWheel
Definition: LArWheelSolid_type.h:24
OuterElectrodBackCone
@ OuterElectrodBackCone
Definition: LArWheelSolid_type.h:34
OuterGlueBackCone
@ OuterGlueBackCone
Definition: LArWheelSolid_type.h:35
LArWheelSolidDDProxy
Definition: LArWheelSolidDDProxy.h:17
InnerLeadCone
@ InnerLeadCone
Definition: LArWheelSolid_type.h:28
InnerAbsorberModule
@ InnerAbsorberModule
Definition: LArWheelSolid_type.h:17
CLHEPtoEigenConverter.h
Geo2G4SolidFactory.h
OuterElectrodWheel
@ OuterElectrodWheel
Definition: LArWheelSolid_type.h:16
LArWheelSolid
Definition: LArWheelSolid.h:94
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
toEMECData.h
xAOD::vertexType
vertexType
Definition: Vertex_v1.cxx:166
DecodeVersionKey.h
OuterAbsorberFrontCone
@ OuterAbsorberFrontCone
Definition: LArWheelSolid_type.h:29
DeMoScan.index
string index
Definition: DeMoScan.py:364
IRDBRecord.h
Definition of the abstract IRDBRecord interface.
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
toEMECData
EMECData toEMECData(IRDBAccessSvc *rdbAccess, const DecodeVersionKey &larVersionKey)
Definition: toEMECData.h:14
Amg::EigenTransformToCLHEP
HepGeom::Transform3D EigenTransformToCLHEP(const Amg::Transform3D &eigenTransf)
Converts an Eigen-based Amg::Transform3D into a CLHEP-based HepGeom::Transform3D.
Definition: CLHEPtoEigenConverter.h:120
LArWheelSolidDDProxy.h
InnerAbsorberCone
@ InnerAbsorberCone
Definition: LArWheelSolid_type.h:25
LArWheelSliceSolid
Definition: LArWheelSliceSolid.h:46
IRDBRecordset.h
Definition of the abstract IRDBRecordset interface.
IGeoModelSvc.h
error
Definition: IImpactPoint3dEstimator.h:70
OuterAbsorberWheel
@ OuterAbsorberWheel
Definition: LArWheelSolid_type.h:14
customSolidMap
std::map< std::string, G4VSolid *, std::less< std::string > > customSolidMap
Definition: Geo2G4SolidFactory.cxx:76