"Universal Solids" library
Notes - version 1.5.1, 25 May 2011 @15:45 CEST+
Editors: J. Apostolakis, G. Cosmo
Contributors: J. Apostolakis, G. Cosmo, A. Gheata, Astrid M., T. Nikitina
- API: generic constructor for "cut"-solids, different implementations/classes for each case.
backwards compatibility in constructors API.
Foundations:
- Independent Vector 'bucket' struct/class - no functionality beyond passing values of x,y,z components
- Tolerance defines the half-thickness of the surface, must be a global value. Once it is set, the tolerance cannot be changed (so it is Write Once, Read Many times-=WORM). Eventually it will be set based on the value of the "world" diameter.)
- SetUnitLength( std::string NameOfUnit );
- GetUnitLength() returns std::string
(TODO: integrate into a specialized class/singleton.)
VUSolid's Main methods
- EInside Inside (point-vector) const
o returns enum {In, Out, Surface}
- double SafetyFromIn (point-vector, bool accurate=false) const
double SafetyFromOut (point-vector, bool accurate=false) const
o return approximated distance (double) from a surface
o must be fast, can think to provide also a "precise" version, at the cost of performance (to be investigated)
o should be optimized for big distances
- double DistanceToIn(point-vector, direction-vector) const
double DistanceToOut(point-vector, direction-vector, &normal-vector, &bool convex) const
o return the exact distance (double) from a surface, given a direction
o compute the normal on the surface, returned as argument, calculated
within the method to verify if it is close to the surface or not
o for DistanceToOut(), normal-vector and convexity flag are mandatory:
If 'convex' is 'true' then the solid is fully behind it, (call it "convex at this point")
If 'convex' is 'false' either the solid extends beyond this plane or it could not guarantee otherwise.
o for DistanceToIn(), the normal-vector could be added as optional
- bool ComputeNormal(point-vector, &direction-vector) const
o computes the normal on a surface and returns it as a direction vector
o should return a valid vector also in case the point is not on the surface, for safety
o should treat cases on corners, to avoid returning invalid normal
o return argument, a Boolean as validity flag
- void Extent(EAxis, &min, &max) const
o returns the minimum and maximum extent along the specified Cartesian axis
o expect it to use internally a GetBBox()/CalculateBBox() method to compute the extent
Decision: whether to store the computed BBox (containing or representing 6 double values), and whether to compute it at construction time
Note: thread-safety is an issue in parameterised volumes - where the dimension can change at runtime).
Implementation Issue: The bounding-box can be an auxiliary class/bucket used by each solid.
VUSolid's Auxiliary methods
- double Capacity(); // was CubicVolume()
- double SurfaceArea()
- point-vector SamplePointOnSurface() const
- point-vector SamplePointInVolume() const
- point-vector SamplePointOnEdges() const
o generates points on the edges of a solid - primarily for testing purposes
o for solids composed only of curved surfaces(like full spheres or toruses) or where an implementation is not available, it defaults to PointOnSurface.
- VUSolid* Clone() const
o provide a new object which is a clone of the solid
- ComputeMesh() - for visualization NOT discussed
// The definitive version of the interface is in the VUSolid class interface,
// currently at /afs/cern.ch/user/j/japost/public/VuSolid.hh
Open issues
- Extension of EInside enum to include mathematical answer; i.e. addition of kInSurface, kOutSurface
Does the adoption of the mathematical answer matter at all? For Boolean operations? Need to investigate further.
- Thread safety: should always be taken into account; i.e. caching of values which may vary during run (parameterised volumes)
- Exceptions: when and where throw them? Agreed to throw in constructors; other reasons tbd (to be determined.)
- Challenging use case for double checking: Propagation inside the surface layer (of a flat surface).
- Secondary issues
- Dot product tolerance (angular tolerance), radial relative tolerance
- Fixed theta0 angle in implementation
- Implementation of Extent(); caching or not bounding-box
- SVN repository (!)
- Bridge classes can be implemented and the box tested with the internal tools of G4 and TGeo
Implementation details
- DistanceToOut() defaults to zero if it finds no exiting surfaces; ignores first solution if the dot-product is less than the tolerance
Tests
- 1. Inside(), DistToIn/Out(), singularities on boundary crossing
- Generate random points inside the solid (use Inside()) and random directions for each of them
- For each, compute d1 = DistToOut() and propagate (d1-tolerance)
- Compute DistToIn() (dnext); must be dnext>tolerance (second crossing or nothing, first boundary not seen)
- Propagate of min(dmax,dnext) to get outside solid (d2), dmax is the maximum extent of the BBox
- Revert direction and compute DistToIn() (d3)
- Compute |d3 - d2| < Err*d2 and plot it
- Propagate back by d3-tolerance (point outside)
- Compute DistToOut() (d4); must be d1<d4<dmax
- 2. Safety()
- Generate random points inside 2*BBox
- Comute Safety() for each of them and generate random directions
- For each, compute the distance to the solid (DistToIn() or DistToOut() depending on Inside() result)
- Compare the distance to the value of the safety; must be dist > safety.
- 3. Normal()
- Generate random points inside the solid and random directions for each of them
- For each propagate by DistToOut() to surface and reflect randomly so that (norm).(dir)<0 and compute DistToOut()
- DistToOut() must never be zero
- Visualize intersection (corners and edges will be most exercised)
- SBT test
- Provides integrated tests for Inside(), Safety(), DistToOut/In() in different setups
- Defines grid of lines (of tunable granularity) on a world bigger at least twice the solid's extent
- Generates random points inside each cell of the grid (may be inside/outside of the solid)
- Consider pair of points, one inside and one outside the solid
- Select direction versus inside
- Must be DistToIn() < infinity (and less the distance between the two points)
- Compute SafetyFromOut() (d1), cannot be bigger than DistToIn()
- Propagate to surface by d1, and compute Inside(); it must give 'kSurface', otherwise report overshoot or undershoot
- Compute SafetyFromIn(), must be zero
- Compute DistToOut(), should not be zero and be smaller than the extent along that direction
- Compute DistToIn(), has to be zero
- Invert direction (towards outside)
- Compute SafetyFromOut(), must be zero
- Compute DistToIn(), must be greater than zero
- Compute DistToOut(), must be zero
- Compare the computed normals and make the dot product with direction, must be negative
- Visualize errors with 'Fred' application
- Optical photons test (optical escape)
- Provides integrated tests for DistToOut()/In() and Normal()
- Define reflections on the surface; generate random points outside, propagate it to surface
- For each, calculate the normal on each intersection point and reflects track
- Reports error when normal is not valid
- Visualize tracks
- Accuracy test for DistanceToIn/Out()
- Generate random points in the world (may be inside or outside the solid)
- Generate random point on surface
- Calculate DistToIn() from any point outside in direction to the point on surface, taking care of multiple intersections
- Compute numerical error comparing to the real distance
- Same for points inside the solid for DistanceToOut()
- Accuracy of points on surface
- Generate random points on surface
- Compute random directions for each point and check reply of DistToIn() and DistToOut()
- Cross-comparison of solids
- Verify response of DistToIn/Out()'Safety()... of different solids of same shape but obtained from different classes (box, trap, polyhedra, ...)
- Additional tests may apply for curved solids for local angular tolerances, by computing the error against the real computed value
- Should standardize on the output of the tests in order to be able to visualize them with a single program.
Todos:
- (Andrei): Bridge class to TGeo Shape
- (John, Gabriele, Tatiana): Bridge class to Geant4 G4VSolid
- (Andrei, John): First draft of UBox (John DistanceToOut, Andrei the rest.)
- Additional parameter to DistanceToIn/Out(..., proposedStep) to discuss. If during computation the distance reveals to be bigger than proposed step, return BIG.
- Won't affect functionality - default value BIG = ignored. Can be ignored by certain solids.
Notes for the meeting on June 7 (John, Andrei, Gabiele, Tatiana)
- First implementation of UBox using internal math utilities and UVector3 available. This uses a simple Makefile and /src /include directories, compiling into libUSolids.so
- Available at: /afs/cern.ch/user/a/agheata/public/USolids partially discussed
- To do: SVN repository (Gabriele, John)
- Coding conventions:
- Class naming: USomething and VUSomething for virtual base classes
- Indenting 3 spaces, no tab characters
- Variable naming: aSomething for arguments, rSomething for return values, fSomething for non-static data members and fgSomething for static ones, lower case starting letter for the others
- Keep significant names for variables: aDirection and not aD
- Discussed behavior of DistToIn and DistToOut when grazing the surface with norm.dot.direction close to 0. Current understanding:
- DistToIn() returns 0 if n.dot.d<=0 and ignore current surface otherwise. Should this happen for n.dot.d<-angular_tolerance ?
- DistToOut() returns 0 if n.dot.d>0 and ignore current surface otherwise. Should the limit be for n.dot.d>angular_tolerance ?
- Homework: Implement bridge classes so that we can test the box using native tools