Geometry¶
What can be extended ?¶
Geant4 allows a user to describe a wide variety of shapes, and to use them as solids in a detector description. In some cases, however, the user may want or need to extend Geant4’s geometry. Solids bounded by cubic or higher order surfaces, or specialised shapes such as tubes twisted on a helix would require a new type of solid. Another reason could be that the user is looking to obtain a speedup by utilising specialised knowledge about his or her geometry - compared to types of solids and implementations which are more general. The most evident case of this occurs when a particular and complex type of solid is a key element for a specific detector geometry; in that case the investment in improving its runtime performance may be worthwhile.
To extend the functionality of the Geometry in this way, a toolkit developer must implement nine methods required for a new solid. We list these methods below and document their specifications. Note that the implementation of several methods are not a trivial matter: these methods must find whether a point is inside a solid, calculate the intersection of a line with the solid, and estimate the minimum distance to the solid along any direction. Once the new solid class has been created, having fulfilled all its specifications by implements the abstract interface of the G4VSolid base class, it can be used like any Geant4 solid,
Other additions can also potentially be achieved. For example, an advanced user could add a new way of creating physical volumes. However, because each type of volume has a corresponding navigator helper, this requires creating a new type of Navigator as well. To do this the user have to inherit from G4Navigator and modify the new Navigator to handle this type of volumes.
Since Geant4 10.6 a new way has been provided to extend the geometry description and G4Navigator using an external geometry modeller. This can be used to support alternative types of physical volumes.
Adding a new type of Solid¶
We list below the required methods for integrating a new type of solid in Geant4. Note that Geant4’s specifications for a solid pay significant attention to what happens at points that are within a small distance (tolerance, kCarTolerance in the code) of the surface. So special care must be taken to handle these cases in considering all different possible scenarios, in order to respect the specifications and allow the solid to be used correctly by the other components of the geometry module.
Creating a derived class of G4VSolid
The solid must inherit from G4VSolid or one of its derived classes and implement its virtual functions.
Mandatory member functions you must define are the following pure virtual of G4VSolid:
EInside Inside(const G4ThreeVector& p)
G4double DistanceToIn(const G4ThreeVector& p)
G4double DistanceToIn(const G4ThreeVector& p, const G4ThreeVector& v)
G4ThreeVector SurfaceNormal(const G4ThreeVector& p)
G4double DistanceToOut(const G4ThreeVector& p)
G4double DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
const G4bool calcNorm=false,
G4bool *validNorm=0, G4ThreeVector *n)
G4bool CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin,
G4double& pMax) const
G4GeometryType GetEntityType() const
std::ostream& StreamInfo(std::ostream& os) const
They must perform the following functions
EInside Inside(const G4ThreeVector& p)
This method must return:
kOutside if the point at offset p is outside the shape boundaries plus Tolerance/2,
kSurface if the point is <= Tolerance/2 from a surface, or
kInside otherwise.
G4ThreeVector SurfaceNormal(const G4ThreeVector& p)
Return the outwards pointing unit normal of the shape for the surface closest to the point at offset p.
G4double DistanceToIn(const G4ThreeVector& p)
Calculate distance to nearest surface of shape from an outside point p. The distance can be an underestimate.
G4double DistanceToIn(const G4ThreeVector& p, const G4ThreeVector& v)
Return the distance along the normalised vector v to the shape, from the point at offset p. If there is no intersection, return kInfinity. The first intersection resulting from ‘leaving’ a surface/volume is discarded. Hence, this is tolerant of points on surface of shape.
G4double DistanceToOut(const G4ThreeVector& p)
Calculate distance to nearest surface of shape from an inside point. The distance can be an underestimate.
G4double DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
const G4bool calcNorm=false,
G4bool *validNorm=0, G4ThreeVector *n=0);
Return distance along the normalised vector v to the shape, from a point at an offset p inside or on the surface of the shape. Intersections with surfaces, when the point is not greater than kCarTolerance/2 from a surface, must be ignored.
If calcNorm is true, then it must also set validNorm to either
true, if the solid lies entirely behind or on the exiting surface. Then it must set n to the outwards normal vector (the Magnitude of the vector is not defined).
false, if the solid does not lie entirely behind or on the exiting surface.
If calcNorm is false, then validNorm and n are unused.
G4bool CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin,
G4double& pMax) const
Calculate the minimum and maximum extent of the solid, when under the specified transform, and within the specified limits. If the solid is not intersected by the region, return false, else return true.
G4GeometryType GetEntityType() const;
Provide identification of the class of an object (required for persistency and STEP interface).
std::ostream& StreamInfo(std::ostream& os) const
Should dump the contents of the solid to an output stream.
The method:
G4VSolid* Clone() const
should be implemented for every solid to provide a way to clone themselves in a new object with same specifications.
The method:
G4ThreeVector GetPointOnSurface() const
returns a random point located on the surface of the solid. Points returned should not necessarily be uniformly distributed.
The method:
G4double GetCubicVolume()
should be implemented for every solid in order to cache the computed value (and therefore reuse it for future calls to the method) and to eventually implement a precise computation of the solid’s volume. If the method will not be overloaded, the default implementation from the base class will be used (estimation through a Monte Carlo algorithm) and the computed value will not be stored.
The method:
G4double GetSurfaceArea()
should be implemented for every solid in order to cache the computed value (and therefore reuse it for future calls to the method) and to eventually implement a precise computation of the solid’s surface area. If the method will not be overloaded, the default implementation from the base class will be used (estimation through a Monte Carlo algorithm) and the computed value will not be stored.
There are a few member functions to be defined for the purpose of visualisation. The first method is mandatory, and the next four are not.
// Mandatory
virtual void DescribeYourselfTo (G4VGraphicsScene& scene) const = 0;
// Not mandatory
virtual G4VisExtent GetExtent() const;
virtual G4Polyhedron* CreatePolyhedron () const;
virtual G4NURBS* CreateNURBS () const;
virtual G4Polyhedron* GetPolyhedron () const;
What these methods should do and how they should be implemented is described here.
void DescribeYourselfTo (G4VGraphicsScene& scene) const;
This method is required in order to identify the solid to the graphics scene. It is used for the purposes of “double dispatch”. All implementations should be similar to the one for G4Box:
void G4Box::DescribeYourselfTo (G4VGraphicsScene& scene) const
{
scene.AddSolid (*this);
}
The method:
G4VisExtent GetExtent() const;
provides extent (bounding box) as a possible hint to the graphics view. You must create it by finding a box that encloses your solid, and returning a VisExtent that is created from this. The G4VisExtent must presumably be given the minus x, plus x, minus y, plus y, minus z and plus z extents of this “box”. For example a cylinder can say
G4VisExtent G4Tubs::GetExtent() const
{
// Define the sides of the box into which the G4Tubs instance would fit.
return G4VisExtent (-fRMax, fRMax, -fRMax, fRMax, -fDz, fDz);
}
The method:
G4Polyhedron* CreatePolyhedron () const;
is required by the visualisation system, in order to create a realistic rendering of your solid. To create a G4Polyhedron for your solid, consult G4Polyhedron.
While the method:
G4Polyhedron* GetPolyhedron () const;
is a “smart” access function that creates on requests a polyhedron and stores it for future access and should be customised for every solid.