SBT README DCW 6/4/99 Solids Batch Test ----------------- This facility is designed to test the correct behavior of CSG solids. It features: 1. Interactive creation of solids. Solid parameters can be specified at the UI interface so that varied tests can be run on solids with different parameters without recompiling the code. 2. Log file. Errors are listed in a log file for later study. 3. Debugging. Errors in a log file can be recreated for later offline debugging. 4. Visualization. Errors in a log file can be recreated offline for visual display, as an aid in debugging. 5. Grids. There is an option to create test trajectories and points along discrete points in space, to test errors at the exact intersections with solid edges and corners. Installation ------------ The standard make file included with SBT links against the full geant4 libraries (much like a geant4 application). It should be possible to produce a makefile that only requires a subset of libraries, but this makefile is not supplied in the package. SBT has been tested on SUN-CC and Linux platforms. General (Interactive) Use ------------------------- The general use of SBT involves the following commands: 1. Choosing a solid (with a "/solid/" command) 2. Specifying geometry test parameters (with a "/test/" command) 3. Running the geometry test (with command "/test/run") 4. Specifying voxel test parameters (with a "/voxel/" command) 5. Running the voxel test (with command "/voxel/run") 6. Repeating as desired Example session: /solid/G4Polycone 0 360 4 (1.0,1.2,1.4,1.2) (-1.0,-1.0,1.0,1.0) /test/maxPoints 100 /test/errorFileName mylogfile.log /test/run Batch Jobs ---------- geant4 command scripts for some solids are supplied. They are given names .geant4, e.g. "box.geant4" and "polycone.geant4". Each script attempts to run a comprehensive test using several variations of each solid, with and without discrete test points. When used they produce several log files. The log file are given the names ..log, e.g. "box.a1.log". The Unix script "runSBT" is included to do the following: 1. Run SBT using a geant4 script 2. Tally up in one line the total number of reported errors in all log files Method: geometry ---------------- SBT creates a set of random points in 3D space, in a Gaussian distribution with adjustable mean and width in each dimension. The default is to generate points with a distribution centered at zero and with a width of 1 meter. This is appropriate for solids of dimensions of roughly 1 meter on each side. Adjustments of the mean is possible with the "/test/target" command and the widths with the "/test/widths" command. Adjustment of these parameters are generally not necessary if enough points are generated but may be desirable in order to make the test more efficient. Adjustment of the mean may also be desirable for discrete points (see description later in this file). For each generated point, SBT first asks the target solid if the point is inside, outside, or on the surface of the solid. Depending on the answer, the point is added to a corresponding list of points. Each of the three lists (of inside, outside, or surface points) contains at most 100 points. If a new point is added to a list that already contains 100 points, it replaces an existing point chosen at random. The limitation of 100 points is intended to keep SBT running roughly in a CPU time of roughly proportional to the total number of points generated. After being added to its list, each inside point is tested against all of the points on the outside list. Similarly, each outside point is tested against all of the points on the inside list. At the moment, no tests are performed on the surface points. The tests are described in more detail below. Any error encountered is written to a log file. The name of the log file by default is "sbt.log", and can be changed with the "/test/errorFileName" command. The format of the log file is described in more detail below. To prevent flooding of the log file by one type of error, if the same error is uncovered more than five times, any remaining such errors are suppressed in the log file. SBT finishes its test when one of the following conditions are met: 1. The total number of random points reaches a maximum 2. The total number of errors reported reaches a maximum Value (1) defaults to 10000 points and is set by command "/test/maxPoints". Value (2) defaults to 100 errors in the log file and is set by command "/test/maxErrors". Method: voxel ------------- To start a voxel test, SBT first generates up to 100000 random points until it finds 1000 points inside the solid (using method G4VSolid::Inside). Afterwards, it starts generating random voxels. It does this by throwing a random number for each x,y,z dimension. If this number is less than 0.2, this coordinate is given no limits. Otherwise, the remaining 0.8 is spread between +/- the range specified in command /voxel/widths (default value is 1 meter). For each random voxel, 20 random offsets are choosen. For these 20 offsets in addition to no offset, the following rotations are tried: 1. No rotation 2. Random rotation around z 3. A further random rotation around x 4. A further random rotation around y 5. A further random rotation around z So, each random sized voxel is tested under 21*5 = 105 different offsets and rotation. Each voxel test consists of calling G4VSolid::CalculateExtent for each of the three coordinate axes. For each axis, if CalculateExtent returns false, the following tests are performed: 1. Make sure none of the 1000 points inside the solid (found earlier) are inside the voxel. Otherwise, if CalculateExtent returns true, the following tests are performed: 1. Make sure all 1000 of the points inside the solid (found earlier) are inside the limits returned. 2. Make sure the min limit is smaller or equal to the max limit. 3. Make sure the min and max limits are not outside the original voxel limits (if there were any) 4. Calculate the set of points spread in the following pattern: 1----2----3 | | | | | | 4----5----6 | | | | | | 7----8----9 along the two axes not being tested to the current voxel limits along those two axes, or to +/- 10 meters if the voxel is not limit only an axis. These nine points are positions at the min and max points in the voxel. SBT then uses G4VSolid::Inside to check whether the points are outside or on the surface of the solid. Choosing the Target Solid ------------------------ The following commands are available for creating solids: /solid/G4Box /solid/G4Para /solid/G4Trap /solid/G4Trd /solid/G4Sphere /solid/G4Torus /solid/G4Tubs /solid/G4Cons /solid/G4Hype /solid/G4Polycone /solid/G4Polyhedra Units are always meters and degrees. The arrays r[] and z[] have the following syntax: ([,...]) | (-) where *no spaces are allowed*. The special array "(-)" is the empty array. Examples: /solid/G4Box 1 1 1 /solid/G4Tubs 0.8 1 1 0 90 /solid/G4Polycone 0 90 4 (1.0,1.2,1.4,1.2) (-1.0,-1.0,1.0,1.0) Log File Format: geometry test ------------------------------ The log file is an ASCII file delimited by newlines. Each line that begins with "%" is a comment. Other lines have the format: where p is the position and v is the (unit) direction most closely associated with the error. Before each such error line, SBT adds a comment describing the error. In addition SBT adds comments concerning the test at the beginning and end of the file. The meaning of the specific errors are described below. Log File Format: voxel test --------------------------- The log file from the voxel test is not made to be machine readable, since the types of errors from this test are too varied. Instead, for each error the word "ERROR" is displayed, and a description of the error follows. The voxel and transform parameters are then displayed. Testing Inside Points --------------------- See routine SBTrun::TestInsidePoint in file src/SBTrun.cc. Each inside point is tested against all points in the outside list. The tests are, in order: 1. DistanceToOut(p) is invoked, where p is the inside point being tested. The result must be greater than 0, or the following error is issued in the log file: "TI: DistanceToOut(p) <= 0" 2. The vector v is calculated from the inside point to the next point in the list of outside points. DistanceToOut(p,v,...) is then invoked. The value must be greater than zero or the following error is issued: "TI: DistanceToOut(p,v) <= 0" The result must not be "kInfinity" or the following error is issued: "TI: DistanceToOut(p,v) == kInfinity" The result must not be less than the value from step (1), or the following error is issued: "TI: DistanceToOut(p,v) < DistanceToIn(p)" 3. If the normal returned by step (2) is valid, the dot product of the normal and v must be greater than zero, or the following error is issued: "TI: Outgoing normal incorrect" 4. A new point p2 = p + dist*v is calculated, where dist is the value found in step (2). Inside(p2) is then invoked. If the results is "kInside", the following error is issued: "TI: DistanceToOut(p,v) undershoots" If the result is "kOutside", the following error is issued: "TI: DistanceToOut(p,v) overshoots" In both cases, the value of p is stored in the log file (not p2). 5. DistanceToIn(p2) is invoked. If the result is not *exactly* zero, the following error is issued: "T02: DistanceToIn(p) should be zero" 6. DistanceToOut(p2) is invoked. If the result is not *exactly* zero, the following error is issued: "T02: DistanceToOut(p) should be zero" 7. DistanceToIn(p2,v) is invoked. If the result is not *exactly* zero, the following error is issued: "T02: DistanceToIn(p,v) should be zero" 8. DistanceToOut(p2,v,...) is invoked. If the result is zero, we have encountered the deadlock condition (track passing through a corner) that currently plagues the CSG solid specifications. The test on this particular outside point is suspended, and step (2) is skipped to for the next outside point on the list. If the result is "kInfinity", the following error is issued: "T02: DistanceToOut(p,v) == kInfinity" 9. If the normal calculated in step (8) is valid, the dot product of the normal and v must be greater than zero, or the following error is issued: "T02: Outgoing normal incorrect" 10. The vector p3 = p2 + dist*v is calculated, where dist is the value returned in step 8. Inside(p3) is then invoked. If the result is "kInside", the following error is issued: "T02: DistanceToOut(p,v) undershoots" If the result is "kOutside", the following error is issued: "TO2: DistanceToOut(p,v) overshoots" 11. If the result of step (8) has a valid normal, DistanceToIn(p3,v) is invoked. If the result is not "kInfinity", the following error is issued: "TO2: DistanceToOut incorrectly returns validNorm==true (line of sight)" (validNorm is to be returned true only if the solid is entirely behind the surface being exited.) 12. If the result of step (8) has a valid normal, the vector p3top = pi - p3 is calculated for all points pi on the inside list. The dot production of p3top with the normal (from step (8)) is then calculated. If this dot product for any inside point is positive, then the following error is issued: "T02: DistanceToOut incorrectly returns validNorm==true (horizon)" (validNorm is to be returned true only if the solid is entirely behind the plane perpendicular to the normal at the exit point.) Testing Outside Points ---------------------- See routine SBTrun::TestOutsidePoint in file src/SBTrun.cc. Each outside point is tested against all points in the inside list. The test are, in order: 1. DistanceToIn(p) is invoked, where p is the target outside point. The result must be greater than zero, or the following error is issued: "T0: DistanceToIn(p) <= 0" 2. The vector v is calculated from the outside point to the next point in the list of inside points. DistanceToIn(p,v) is then invoked. The value must be greater than zero or the following error is issued: "T0: DistanceToIn(p,v) <= 0" The result must not be "kInfinity", or the following error is issued: "T0: DistanceToIn(p,v) == kInfinity" The result must be greater than the value from step (1), or the following error is issued: "T0: DistanceToIn(p,v) < DistanceToIn(p)" 3. A new point p2 = p + dist*v is calculated, where dist is the value found in step (2). Inside(p2) is then invoked. If the results is "kOutside", the following error is issued: "TO: DistanceToOut(p,v) undershoots" If the result is "kInside", the following error is issued: "TO: DistanceToOut(p,v) overshoots" In both cases, the value of p is stored in the log file (not p2). Discrete Points --------------- There is an option of generating random points on a grid. The origin of the grid always corresponds to the mean value (as set by "/test/target"). The spacing of the grid is adjusted by command "/test/gridSizes". Debugging: geometry ------------------- Once a test is run and a log file created, it is possible to read the values from the log file to recreate an error. This is useful in the debugger to discover the precise reason for the error. No check is made that the current solid is identical to the solid used to make the log file. It is up to the user to ensure this (using the appropriate "/solid/" command if necessary). NOTE: This has changed. The current solid is written in the log file So the ErrorView script could convert a log file to a visualization script that could be run by SBT. The following commands are supported: 1. /test/draw Draw the error and the solid (if possible) using the currently selected visualization. 2. /test/debugInside Invokes the "Inside" method of the test solid. 3. /test/debugToInP Invokes the "DistanceToIn(p)" method of the test solid. 4. /test/debugToInPV Invokes the "DistanceToIn(p,v)" method of the test solid. A new point p2 = p + dist*v is calculated, and then the "Inside" method is invoked for that point. 5. /test/debugToOutP Invokes the "DistanceToOut(p)" method of the test solid. 6. /test/debugToOutPV Invokes the "DistanceToOut(p,v,...)" method of the test solid. A new point p2 = p + dist*v is calculated, and then the "Inside" method is invoked for that point. These commands are intended to be in combination with a debugger (such as dbx). To debug a particular error, one sets a break point in the relevant routine(s) and issues the appropriate "/test/" command. The "/test/draw" command may be useful to isolate the problem. Clearly, to use the debugger requires that the geant4 libraries linked to SBT are compiled with the debug flag on (environment variable G4DEBUG). Debugging: voxel ---------------- Included in SBT is a package for displaying voxels and the results of ::CalculateExtent. The commands for this are under the tree /voxel/picture. 1. /voxel/picture/voxel Takes six double numbers (xmin xmax ymin ymax zmin zmax) to specify the voxel dimensions. If any min > max, that dimension is taken to be unlimited. 2. /voxel/picture/translate Takes three double numbers to specify the translation in the voxel. 4. /voxel/picture/rotate Takes four doubles numbers (axisx axisy axisz rotation) to specify the axis and rotation amount to specify the rotation of the voxel. 5. /voxel/picture/point Takes three numbers for an optional point to be displayed along with the voxel and solid shape. 6. /voxel/picture/limit Specifies the voxel limits to be drawn inside the voxel. 7. /voxel/picture/draw Draws the items as specified in the above 1-6 commands. 8. /voxel/picture/debug Invokes ::CalculateExtent and ::Inside for the items as specified in the above 1--6 commands. Useful for running the solid code inside a debugger. Problems -------- Visualization is used in a manner that may not be entirely consistent with its design. This may introduce errors. SBT uses the random number generator G4UniformRand. It does not appear that this random number generator is reproducible across platforms. Recovering an error from a log file sometimes does not reproduce the problem, presumably due to a subtle inaccuracy in translating the double values to and/or from the ASCII log file. This despite writing out 14 digits for the values in the ASCII log file.