Import Geant4 3.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 16:03:00 +02:00
parent cfcb558cfe
commit 137e303ecc
2843 changed files with 37082 additions and 38426 deletions
+92 -30
View File
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4Box.cc,v 1.10 2000/11/20 18:05:59 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// $Id: G4Box.cc,v 1.13 2001/02/01 08:22:19 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-01 $
//
//
//
@@ -17,8 +17,10 @@
// 07.05.00 - V.Grichine: d= DistanceToIn(p,v), if d<e/2, d=0
// 09.06.00 - V.Grichine: safety in DistanceToIn(p) against Inside(p)=kOutside
// and information before exception in DistanceToOut(p,v,...)
// 15.11.00 - D.Williams, V.Grichine: bug fixed in CalculateExtent - change
// algorithm for rotated vertices
//
//
#include "G4Box.hh"
@@ -37,10 +39,11 @@
//
// Constructor - check & set half widths
G4Box::G4Box(const G4String& pName, G4double pX,
G4double pY, G4double pZ) : G4CSGSolid(pName)
G4Box::G4Box(const G4String& pName,
G4double pX, G4double pY, G4double pZ)
: G4CSGSolid(pName)
{
if ( pX > 0 && pY > 0 && pZ > 0 )
if ( pX > 2*kCarTolerance && pY > 2*kCarTolerance&& pZ > 2*kCarTolerance)
{
fDx = pX ;
fDy = pY ;
@@ -48,7 +51,7 @@ G4Box::G4Box(const G4String& pName, G4double pX,
}
else
{
G4Exception("Error in G4Box::Box - negative parameters");
G4Exception("G4Box::G4Box(...) - invalid dimensions");
}
}
@@ -62,6 +65,34 @@ G4Box::~G4Box()
;
}
//////////////////////////////////////////////////////////////////////////////
void G4Box::SetXHalfLength(G4double dx)
{
if(dx > 2*kCarTolerance)
fDx = dx;
else
G4Exception("G4Box::SetXHalfLength(...) - invalid dimensions");
}
void G4Box::SetYHalfLength(G4double dy)
{
if(dy > 2*kCarTolerance)
fDy = dy;
else
G4Exception("G4Box::SetYHalfLength(...) - invalid dimensions");
}
void G4Box::SetZHalfLength(G4double dz)
{
if(dz > 2*kCarTolerance)
fDz = dz;
else
G4Exception("G4Box::SetZHalfLength(...) - invalid dimensions");
}
////////////////////////////////////////////////////////////////////////
//
// Dispatch to parameterisation for replication mechanism dimension
@@ -189,39 +220,70 @@ G4bool G4Box::CalculateExtent(const EAxis pAxis,
ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ;
ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax) ;
ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ;
if ( pMin != kInfinity || pMax != -kInfinity )
{
existsAfterClip = true ;
if (pVoxelLimit.IsLimited(pAxis) == false)
{
if ( pMin != kInfinity || pMax != -kInfinity )
{
existsAfterClip = true ;
// Add 2*tolerance to avoid precision troubles
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
}
pMin -= kCarTolerance;
pMax += kCarTolerance;
}
}
else
{
G4ThreeVector clipCentre(
( pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
( pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
( pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
if ( pMin != kInfinity || pMax != -kInfinity )
{
existsAfterClip = true ;
// Check to see if endpoints are in the solid
clipCentre(pAxis) = pVoxelLimit.GetMinExtent(pAxis);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
{
pMin = pVoxelLimit.GetMinExtent(pAxis);
}
else
{
pMin -= kCarTolerance;
}
clipCentre(pAxis) = pVoxelLimit.GetMaxExtent(pAxis);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
{
pMax = pVoxelLimit.GetMaxExtent(pAxis);
}
else
{
pMax += kCarTolerance;
}
}
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
( pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
( pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
( pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
else if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
{
existsAfterClip = true ;
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
existsAfterClip = true ;
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
}
}
}
delete vertices;
return existsAfterClip;
}
}
}
}
/////////////////////////////////////////////////////////////////////////
//
@@ -646,8 +708,8 @@ G4double G4Box::DistanceToOut(const G4ThreeVector& p) const
G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ;
G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ;
G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ;
// G4Exception("Invalid call in G4Box::DistanceToOut(p), point p is outside") ;
G4cout<<"G4Box::DistanceToOut(p),point p is outside ?!" << G4endl ;
G4Exception("Invalid call in G4Box::DistanceToOut(p), point p is outside") ;
// G4cout<<"G4Box::DistanceToOut(p),point p is outside ?!" << G4endl ;
}
safx1 = fDx - p.x() ;
safx2 = fDx + p.x() ;
+1 -1
View File
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4CSGSolid.cc,v 1.2 1999/12/15 14:50:06 gunter Exp $
// GEANT4 tag $Name: geant4-03-00 $
// GEANT4 tag $Name: geant4-03-01 $
//
#include "G4CSGSolid.hh"
+1 -1
View File
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4Cons.cc,v 1.16 2000/11/20 17:57:58 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// GEANT4 tag $Name: geant4-03-01 $
//
// class G4Cons
//
+1 -1
View File
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4Para.cc,v 1.6 2000/11/20 17:57:59 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// GEANT4 tag $Name: geant4-03-01 $
//
// class G4Para
//
+1 -1
View File
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4Sphere.cc,v 1.8 2000/11/20 17:57:59 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// GEANT4 tag $Name: geant4-03-01 $
//
// class G4Sphere
//
+169 -503
View File
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4Torus.cc,v 1.20 2000/12/01 11:49:03 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// $Id: G4Torus.cc,v 1.23 2001/01/29 13:12:57 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-01 $
//
//
// class G4Torus
@@ -20,6 +20,7 @@
// 26.05.00 V.Grichine, new fuctions developed by O.Cremonesi were added
// 31.08.00 E.Medernach, numerical computation of roots with bounding volume technique
// 03.10.00 E.Medernach, SafeNewton added
// 11.01.01 E.Medernach, Use G4PolynomialSolver to find roots
//
@@ -38,6 +39,7 @@
#include "G4NURBStube.hh"
#include "G4NURBScylinder.hh"
#include "G4NURBStubesector.hh"
#include "G4PolynomialSolver.hh"
// #define DEBUGTORUS 1
@@ -1124,6 +1126,16 @@ G4double G4Torus::DistanceToIn(const G4ThreeVector& p,
const G4ThreeVector& v) const
{
/*
On voudrait arriver a cela:
return SolveNumeric(p, v, true);
Mais des problemes avec la tolerance sur la section Phi
ne le permet pas pour le moment
*/
/*
Le tore mathematique peut etre vu comme une equation implicite
*/
G4double snxt=kInfinity, sphi=kInfinity;// snxt = default return value
G4double c[5], s[4] ;
@@ -2189,14 +2201,10 @@ G4NURBS* G4Torus::CreateNURBS () const
/** Important : the precision could be tuned by TORUSPRECISION **/
#define EPSILON 1e-12
#define INFINITY 1e+12
#define TORUSPRECISION 1.0 // or whatever you want for precision
// (it is TorusEquation related)
#define HOLEBVM 0
#define NBPOINT 6
#define ITERATION 12 // 20 But 8 is really enough for Newton with a good guess
#define NOINTERSECTION kInfinity
/*
Torus implementation with Newton Method and Bounding volume
@@ -2229,14 +2237,13 @@ G4double G4Torus::SolveNumeric(const G4ThreeVector& p,
G4double Value = TorusEquation(p.x(),p.y(),p.z(),GetRtor(),GetRmax());
EInside inside ;
/*** Check from only the exterior torus TORUSPRECISION ? ***/
/** Note that we could be on the surface from the interior torus **/
#if DEBUGTORUS
G4cout << "G4Torus::SolveNumeric " << p << ", " << v << G4endl ;
G4cout << "G4Torus::SolveNumeric Value = " << Value << G4endl;
#endif
if (Value < -TORUSPRECISION) {
inside = kInside ;
} else {
@@ -2255,7 +2262,7 @@ G4double G4Torus::SolveNumeric(const G4ThreeVector& p,
<< " Rtor = " << GetRtor()
<< " Rmax = " << GetRmax() << G4endl ;
#endif
if (fabs(GetRmin()) > EPSILON) {
if (fabs(GetRmin()) > POLEPSILON) {
#if DEBUGTORUS
G4cout << "G4Torus::SolveNumeric Testing interior torus .." << G4endl ;
#endif
@@ -2420,7 +2427,10 @@ G4double G4Torus::SolveNumeric(const G4ThreeVector& p,
/** Now check Phi .. **/
/* Eliminate the case of point (0,0,0) */
if ((p.x()*p.x() + p.y()*p.y() + p.z()*p.z()) > EPSILON)
// if ((p.x()*p.x() + p.y()*p.y() + p.z()*p.z()) > POLEPSILON)
if (((p.x()+ lambda*v.x())*(p.x()+ lambda*v.x()) +
(p.y()+ lambda*v.y())*(p.y()+ lambda*v.y()) +
(p.z()+ lambda*v.z())*(p.z()+ lambda*v.z())) > POLEPSILON)
{
G4double theta ;
@@ -2436,11 +2446,14 @@ G4double G4Torus::SolveNumeric(const G4ThreeVector& p,
#if DEBUGTORUS
G4cout << "G4Torus::SolveNumeric theta = " << theta
<< " Phi = " << fSPhi
<< " Phi + dPhi = " << fSPhi + fDPhi << G4endl ;
<< " Phi + dPhi = " << fSPhi + fDPhi
<< " kAngTolerance = " << kAngTolerance << G4endl ;
G4cout << " theta - Phi = " << theta - fSPhi << G4endl ;
#endif
if ((theta >= fSPhi - kAngTolerance*0.5) &&
(theta <= (fSPhi + fDPhi + kAngTolerance*0.5))) {
if ((theta - fSPhi >= - kAngTolerance*0.5) &&
(theta - (fSPhi + fDPhi) <= kAngTolerance*0.5)) {
/*** If this is the case we return this solution ***/
#if DEBUGTORUS
G4cout << "G4Torus::SolveNumeric Correct Phi section" << G4endl ;
@@ -2511,7 +2524,12 @@ G4double G4Torus::SolveNumeric(const G4ThreeVector& p,
v,IsDistanceToIn);
}
}
} else {
#if DEBUGTORUS
G4cout << "G4Torus::SolveNumeric Phi not checked because point is " << p + lambda*v << G4endl << G4endl;
#endif
}
return lambda;
}
@@ -2534,13 +2552,17 @@ void G4Torus::BVMIntersection(G4double x,G4double y,G4double z,
DistToZ = (x+NewL[0]*dx)*(x+NewL[0]*dx) + (y+NewL[0]*dy)*(y+NewL[0]*dy);
if (DistToZ - (Rmax + Rmin)*(Rmax + Rmin) > 0)
valid[0] = 0;
#if HOLEBVM
if (DistToZ - (Rmax - Rmin)*(Rmax - Rmin) < 0)
valid[0] = 0;
#endif
DistToZ = (x+NewL[1]*dx)*(x+NewL[1]*dx) + (y+NewL[1]*dy)*(y+NewL[1]*dy);
if (DistToZ - (Rmax + Rmin)*(Rmax + Rmin) > 0)
valid[1] = 0;
#if HOLEBVM
if (DistToZ - (Rmax - Rmin)*(Rmax - Rmin) < 0)
valid[1] = 0;
#endif
} else {
/* if dz == 0 we could know the exact solution */
/* Well, this is true but we have not expected precision issue from sqrt .. */
@@ -2564,63 +2586,65 @@ void G4Torus::BVMIntersection(G4double x,G4double y,G4double z,
valid[3] = 0;
NewL[2] = -1.0;
NewL[3] = -1.0;
} else {
} else{
d = sqrt(d) ;
NewL[2] = (d - b)/(2*a);
NewL[3] = (-d - b)/(2*a);
if (NewL[2] < 0.0) valid[2] = 0;
if (fabs(z + NewL[2]*dz) - Rmin > EPSILON) valid[2] = 0;
if (fabs(z + NewL[2]*dz) - Rmin > POLEPSILON) valid[2] = 0;
if (NewL[3] < 0.0) valid[3] = 0;
if (fabs(z + NewL[3]*dz) - Rmin > EPSILON) valid[3] = 0;
if (fabs(z + NewL[3]*dz) - Rmin > POLEPSILON) valid[3] = 0;
}
} else {
/* only dz != 0 so we could know the exact solution */
/* this depends only for the distance to Z axis */
/* BUT big precision problem near the border.. */
/* I like so much Newton to increase precision you know.. */
} else
{
/* only dz != 0 so we could know the exact solution */
/* this depends only for the distance to Z axis */
/* BUT big precision problem near the border.. */
/* I like so much Newton to increase precision you know.. */
NewL[2] = -1.0;
NewL[3] = -1.0;
valid[2] = 0;
valid[3] = 0;
NewL[2] = -1.0;
NewL[3] = -1.0;
valid[2] = 0;
valid[3] = 0;
/*** Try This to see precision issue with sqrt(~ 0)
G4double DistToZ ;
G4double result;
G4double guess;
/*** Try This to see precision issue with sqrt(~ 0)
G4double DistToZ ;
G4double result;
G4double guess;
DistToZ = sqrt(x*x + y*y) ;
DistToZ = sqrt(x*x + y*y) ;
if ((DistToZ < (Rmax - Rmin)) || (DistToZ > (Rmax + Rmin))) {
return -1.0 ;
}
if ((DistToZ < (Rmax - Rmin)) || (DistToZ > (Rmax + Rmin))) {
return -1.0 ;
}
result = sqrt((Rmin + Rmax - DistToZ)*(Rmin - Rmax + DistToZ));
result = sqrt((Rmin + Rmax - DistToZ)*(Rmin - Rmax + DistToZ));
if (dz < 0) {
if (z > result) {
return (result - z)/dz;
} else {
if (z > -result) {
return (-result - z)/dz;
} else
return -1.0;
}
} else {
if (z < -result) {
return (z + result)/dz;
} else {
if (z < result) {
return (z - result)/dz;
} else
return -1.0;
}
}
*/
}
if (dz < 0) {
if (z > result) {
return (result - z)/dz;
} else {
if (z > -result) {
return (-result - z)/dz;
} else
return -1.0;
}
} else {
if (z < -result) {
return (z + result)/dz;
} else {
if (z < result) {
return (z - result)/dz;
} else
return -1.0;
}
}
*/
}
/* x² + y² = (Rmax - Rmin)² */
#if HOLEBVM
if ((dx != 0) || (dy != 0)) {
G4double a,b,c,d;
@@ -2639,18 +2663,20 @@ void G4Torus::BVMIntersection(G4double x,G4double y,G4double z,
NewL[4] = (d - b)/(2*a);
NewL[5] = (-d - b)/(2*a);
if (NewL[4] < 0.0) valid[4] = 0;
if (fabs(z + NewL[4]*dz) - Rmin > EPSILON) valid[4] = 0;
if (fabs(z + NewL[4]*dz) - Rmin > POLEPSILON) valid[4] = 0;
if (NewL[5] < 0.0) valid[5] = 0;
if (fabs(z + NewL[5]*dz) - Rmin > EPSILON) valid[5] = 0;
if (fabs(z + NewL[5]*dz) - Rmin > POLEPSILON) valid[5] = 0;
}
} else
#endif
{
/* only dz != 0 so we could know the exact solution */
/* OK but same as above .. */
valid[4] = 0;
valid[5] = 0;
NewL[4] = -1.0;
NewL[5] = -1.0;
}
} else {
/* only dz != 0 so we could know the exact solution */
/* OK but same as above .. */
valid[4] = 0;
valid[5] = 0;
NewL[4] = -1.0;
NewL[5] = -1.0;
}
}
void G4Torus::SortIntervals (G4double *SortL, G4double *NewL,
@@ -2660,7 +2686,7 @@ void G4Torus::SortIntervals (G4double *SortL, G4double *NewL,
G4double swap;
(*NbIntersection) = 0;
SortL[0] = -INFINITY;
SortL[0] = -kInfinity;
for (i=0;i<6;i++) {
if (valid[i] != 0) {
@@ -2679,7 +2705,7 @@ void G4Torus::SortIntervals (G4double *SortL, G4double *NewL,
/* Delete double values */
/* When the ray hits a corner we have a double value */
for (i=0;i<(*NbIntersection)-1;i++) {
if (SortL[i+1] - SortL[i] < EPSILON) {
if (SortL[i+1] - SortL[i] < POLEPSILON) {
if (((*NbIntersection) & (1)) == 1) {
/* If the NbIntersection is odd then we keep one value */
for (j=i+1;j<(*NbIntersection);j++) {
@@ -2706,7 +2732,8 @@ G4double G4Torus::DistanceToTorus (G4double x,G4double y,G4double z,
G4double dx,G4double dy,G4double dz,
G4double Rmax,G4double Rmin) const
{
G4double Lmin,Lmax;
G4double Lmin=0.;
G4double Lmax=0.;
G4double guess;
G4double SortL[4];
@@ -2733,16 +2760,16 @@ G4double G4Torus::DistanceToTorus (G4double x,G4double y,G4double z,
SortIntervals(SortL,NewL,valid,&NbIntersection);
{
/*** Length check ***/
/*** Length check (Torus specific) ***/
G4double LengthMin = 0.82842712*Rmin;
switch(NbIntersection) {
case 1:
if (SortL[0] < EPSILON) {
if (SortL[0] < POLEPSILON) {
if (fabs(TorusEquation(x,y,z,Rmax,Rmin)) < TORUSPRECISION) {
return 0.0;
} else {
return NOINTERSECTION;
return kInfinity;
}
}
break;
@@ -2750,7 +2777,7 @@ G4double G4Torus::DistanceToTorus (G4double x,G4double y,G4double z,
if ((SortL[1] - SortL[0]) < LengthMin) NbIntersection = 0;
break;
case 3:
if (SortL[0] < EPSILON) {
if (SortL[0] < POLEPSILON) {
if (fabs(TorusEquation(x,y,z,Rmax,Rmin)) < TORUSPRECISION) {
return 0.0;
} else {
@@ -2785,454 +2812,93 @@ G4double G4Torus::DistanceToTorus (G4double x,G4double y,G4double z,
}
#endif
/*** If the ray intersects the torus it necessary intersects the BVMax ***/
/*** So it is necessary into *an* interval from the BVM ***/
/** Note : In general there are only 2 intersections so computing the second
interval could be done only if the first one does not contain any root */
/* NOW there is 2 possibilities */
/* If inside the BVM (or Torus instead), take "0, SortL[0] .." */
/* If outside the BVM, we have intervals where if there is an intersection
the root must be */
/* Now Lmin1 <= Lambda <= Lmax and there is a root */
/* Newton Methods in this interval from the guess */
/*** Beware The first interval could be the bad one and we have to see other one ***/
/*** We must have a way to decide if an interval contains root or not .. ***/
/***
Beware: If the original point is near the torus (into the BVM not the torus)
we have serious precision issue (bad guess value) try it with a big Rmin
***/
/* We are Inside the BVM if the number of intersection is odd */
/* Not necessary an intersection with Torus if point outside Torus and Inside BVM ! */
if (((NbIntersection) & (1)) != 0) {
/*** If we are Inside the BVM Lmin = 0. Lmax is the point ***/
/*** there is necessary an intersection if the point is inside the Torus ***/
G4int InsideTorus = 0;
switch (NbIntersection) {
case 0:
return kInfinity ;
break;
case 1:
Lmin = 0.0 ;
Lmax = SortL[0] ;
if (TorusEquation(x,y,z,Rmax,Rmin) < 0.0) {
InsideTorus = 1;
/* As we are inside the torus it must have an intersection */
/* To have a good guess we take Lmax - Rmin/8.0 */
/* If we are inside the torus the upper bound is better */
guess = Lmax - Rmin*0.125;
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus Inside the torus" << G4endl ;
G4cout << "G4Torus::DistanceToTorus Initial Guess is "
<< guess << G4endl ;
#endif
} else {
#if DEBUGTORUS
G4cout.precision(16);
G4cout << "G4Torus::DistanceToTorus point " << x << ", " << y
<< ", " << z << ", " << " is outside the torus "
<< " Rmax = " << Rmax << " Rmin = " << Rmin << " Teq = "
<< TorusEquation(x,y,z,Rmax,Rmin) << G4endl ;
#endif
InsideTorus = 0;
/* PROBLEMS what to choose ? */
guess = 0.0; //0.0 ?
}
/* Ready to do Newton */
guess = Newton(guess,x,y,z,dx,dy,dz,Rmax,Rmin,Lmin,Lmax);
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus First Newton guess = "
<< guess << G4endl ;
G4cout << "G4Torus::DistanceToTorus Lmin = " << Lmin
<< " Lmax = " << Lmax << G4endl ;
#endif
/* In case the origin point is just in the surface
the NbIntersection will be odd and guess will be zero
Anyway, it is correct to say that distance is zero but
we want to return +inf if we are exiting the solid
So ..
*/
/* Check here is the root found is into interval */
if ((guess >= (Lmin - EPSILON)) && (guess <= (Lmax + EPSILON))) {
return guess ;
} else {
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus Point does not appear to be in the interval guess = "
<< guess
<< " Lmin = " << Lmin - EPSILON << " Lmax = "
<< Lmax + EPSILON << G4endl ;
#endif
if (NbIntersection == 3) {
/** OK we are in the small part around the BVM **/
/** So we check the second interval **/
Lmin = SortL[1];
Lmax = SortL[2];
guess = Lmin;
guess = Newton(guess,x,y,z,dx,dy,dz,Rmax,Rmin,Lmin,Lmax);
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus Second Newton guess = "
<< guess << G4endl ;
G4cout << "G4Torus::DistanceToTorus Lmin = " << Lmin
<< " Lmax = " << Lmax << G4endl ;
#endif
if ((guess >= (Lmin - EPSILON)) && (guess <= (Lmax + EPSILON))) {
return guess;
} else {
return NOINTERSECTION;
}
} else {
if (InsideTorus == 1) {
/* Incredible : sometimes precisions errors bring us here
with guess = SortL[0]
So we return guess ..
*/
G4cout << "G4Torus: Root not found .." << G4endl ;
G4cout << "Point: "<< x << " " << y << " " << z << G4endl ;
G4cout << "Dir : "<< dx << " " << dy << " " << dz << G4endl ;
return guess;
}
return NOINTERSECTION;
}
}
} else { // Outside
/*** If we are Out then we need more to know if intersection exists ***/
/*** there is 2 intersection points at least (perhaps the same) with BVMax ***/
/*** Return if no intersection with BVMax ***/
if (NbIntersection == 0)
return NOINTERSECTION ;
break;
case 2:
Lmin = SortL[0] ;
Lmax = SortL[1] ;
/** Lmin because it is probably near the BVM entry point **/
/** PROBLEM if the ray hits the top of BVM with a small angle
then the interval is too big and the guess is bad **/
guess = Lmin ;
break;
#if HOLEBVM
case 3:
Lmin = 0.0 ;
Lmax = SortL[0] ;
TorusEquationClass torus (Rmax,Rmin);
torus.setPosition(x,y,z);
torus.setDirection(dx,dy,dz);
G4PolynomialSolver<TorusEquationClass,G4double(TorusEquationClass::*)(G4double)>
PolySolver(&torus,
&TorusEquationClass::Function,
&TorusEquationClass::Derivative,
TORUSPRECISION) ;
/*** We know only that if there is a solution, it is between Lmin and Lmax ***/
/*** But we are not sure that there is one ... ***/
/* Ready to do Newton */
guess = Newton(guess,x,y,z,dx,dy,dz,Rmax,Rmin,Lmin,Lmax);
guess = PolySolver.solve(Lmin,Lmax);
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus Newton with 2 or 4 points : "
<< guess << G4endl ;
#endif
/* Check here is the root found is into interval */
if ((guess >= (Lmin - EPSILON)) && (guess <= (Lmax + EPSILON))) {
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus Newton gives a point into interval (Ok)"
<< G4endl ;
#endif
return guess;
} else {
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus Newton does not give a point into interval (Ko)"
<< G4endl ;
#endif
if (NbIntersection == 4) {
/* Well if that does not converge with the first interval try with the other one */
Lmin = SortL[2] ;
Lmax = SortL[3] ;
guess = Lmin;
guess = Newton(guess,x,y,z,dx,dy,dz,Rmax,Rmin,Lmin,Lmax);
if ((guess >= (Lmin - EPSILON)) && (guess <= (Lmax + EPSILON))) {
return guess;
} else {
return NOINTERSECTION;
}
} else {
/* Certainly this is due to the BVM part that is not in Torus */
return NOINTERSECTION ;
}
if ((guess >= (Lmin - POLEPSILON)) && (guess <= (Lmax + POLEPSILON))) {
return guess ;
} else {
Lmin = SortL[1] ;
Lmax = SortL[2] ;
}
}
}
break;
case 4:
Lmin = SortL[0] ;
Lmax = SortL[1] ;
G4int G4Torus::SafeNewton(G4double x, G4double y, G4double z,
G4double dx, G4double dy, G4double dz,
G4double Rmax, G4double Rmin,
G4double *Lmin,G4double *Lmax) const
{
/** SafeNewton is a clipping interval Newton method **/
/** This method is at least 3 times slower than Newton but is sure to work **/
/** So it could be better to use it when Newton is not enough **/
TorusEquationClass torus (Rmax,Rmin);
torus.setPosition(x,y,z);
torus.setDirection(dx,dy,dz);
G4double P[5][2],D[2] ;
G4double Lx,Ly,Lz ;
G4double NewMin,NewMax;
G4int IntervalIsVoid = 1;
G4int NewtonIsSafe = 0;
/*** Calculating Control Points ***/
/*
0 p0 = F((*Lmin))
1/4 p1 = F((*Lmin)) + ((*Lmax) - (*Lmin))/4 * F'((*Lmin))
2/4 p2 = 1/6 * (16*F(((*Lmax) + (*Lmin))/2) - (p0 + 4*p1 + 4*p3 + p4))
3/4 p3 = F((*Lmax)) - ((*Lmax) - (*Lmin))/4 * F'((*Lmax))
1 p4 = F((*Lmax))
*/
G4PolynomialSolver<TorusEquationClass,G4double(TorusEquationClass::*)(G4double)>
PolySolver(&torus,
&TorusEquationClass::Function,
&TorusEquationClass::Derivative,
TORUSPRECISION) ;
Lx = x + (*Lmin)*dx;
Ly = y + (*Lmin)*dy;
Lz = z + (*Lmin)*dz;
guess = PolySolver.solve(Lmin,Lmax);
D[0] = dx*TorusDerivativeX(Lx,Ly,Lz,Rmax,Rmin);
D[0] += dy*TorusDerivativeY(Lx,Ly,Lz,Rmax,Rmin);
D[0] += dz*TorusDerivativeZ(Lx,Ly,Lz,Rmax,Rmin);
P[0][0] = (*Lmin);
P[0][1] = TorusEquation(Lx,Ly,Lz,Rmax,Rmin);
if (fabs(P[0][1]) < TORUSPRECISION) {
NewtonIsSafe = 1;
return NewtonIsSafe;
}
if (((*Lmax) - (*Lmin)) < EPSILON) {
return 1;
}
P[1][0] = (*Lmin) + ((*Lmax) - (*Lmin))/4;
P[1][1] = P[0][1] + (((*Lmax) - (*Lmin))/4.0) * D[0];
Lx = x + (*Lmax)*dx;
Ly = y + (*Lmax)*dy;
Lz = z + (*Lmax)*dz;
D[1] = dx*TorusDerivativeX(Lx,Ly,Lz,Rmax,Rmin);
D[1] += dy*TorusDerivativeY(Lx,Ly,Lz,Rmax,Rmin);
D[1] += dz*TorusDerivativeZ(Lx,Ly,Lz,Rmax,Rmin);
P[4][0] = (*Lmax);
P[4][1] = TorusEquation(Lx,Ly,Lz,Rmax,Rmin);
P[3][0] = (*Lmax) - ((*Lmax) - (*Lmin))/4;
P[3][1] = P[4][1] - ((*Lmax) - (*Lmin))/4 * D[1];
Lx = x + ((*Lmax)+(*Lmin))/2*dx;
Ly = y + ((*Lmax)+(*Lmin))/2*dy;
Lz = z + ((*Lmax)+(*Lmin))/2*dz;
P[2][0] = ((*Lmax) + (*Lmin))/2;
P[2][1] = (16*TorusEquation(Lx,Ly,Lz,Rmax,Rmin)
- (P[0][1] + 4*P[1][1] + 4*P[3][1] + P[4][1]))/6 ;
#if DEBUGTORUS
G4cout << "G4Torus::SafeNewton Lmin = " << (*Lmin) << G4endl ;
G4cout << "G4Torus::SafeNewton Lmax = " << (*Lmax) << G4endl ;
G4cout << "G4Torus::SafeNewton P[0] = " << P[0][1] << G4endl ;
G4cout << "G4Torus::SafeNewton P[1] = " << P[1][1] << G4endl ;
G4cout << "G4Torus::SafeNewton P[2] = " << P[2][1] << G4endl ;
G4cout << "G4Torus::SafeNewton P[3] = " << P[3][1] << G4endl ;
G4cout << "G4Torus::SafeNewton P[4] = " << P[4][1] << G4endl ;
#endif
/** Ok now we have all control points, we could compute the convex area **/
/** Problems:
- if there is one point with a ~ 0 coordinate and all the other the
same sign we miss the value
- if there are more than a root in the interval then the interval
length does not decrease to 0. A solution may be to split intervals
in the middle but how to know when we must split ?
**/
/*** For each points make 2 sets. A set of positive points and a set
of negative points ***/
/*** Note: could be better done with scalar product .. ***/
/**
We have to compute convex area of the control point before
applying intersection with y=0
**/
/* there is an intersection only if each have different signs */
/* PROBLEM : If a control point have a 0.00 value the sign check is wrong
try to solve that with TORUSPRECISION ..
*/
{
G4double Intersection ;
G4int i,j;
NewMin = (*Lmax) ;
NewMax = (*Lmin) ;
for (i=0;i<5;i++)
for (j=i+1;j<5;j++)
{
/* there is an intersection only if each have different signs */
if (((P[j][1] > -TORUSPRECISION) && (P[i][1] < TORUSPRECISION)) ||
((P[j][1] < TORUSPRECISION) && (P[i][1] > -TORUSPRECISION))) {
IntervalIsVoid = 0;
Intersection = P[j][0] - P[j][1]*((P[i][0] - P[j][0])
/(P[i][1] - P[j][1]));
if (Intersection < NewMin) {
NewMin = Intersection;
}
if (Intersection > NewMax) {
NewMax = Intersection;
}
}
}
if (IntervalIsVoid != 1) {
(*Lmax) = NewMax;
(*Lmin) = NewMin;
if ((guess >= (Lmin - POLEPSILON)) && (guess <= (Lmax + POLEPSILON))) {
return guess ;
} else {
Lmin = SortL[2] ;
Lmax = SortL[3] ;
}
}
if (IntervalIsVoid == 1) {
return -1;
}
return NewtonIsSafe;
}
G4double G4Torus::Newton (G4double guess,
G4double x, G4double y, G4double z,
G4double dx, G4double dy, G4double dz,
G4double Rmax, G4double Rmin,
G4double Lmin,G4double Lmax) const
{
/* So now we have a good guess and an interval where
if there are an intersection the root must be */
G4double Lx = 0;
G4double Ly = 0;
G4double Lz = 0;
G4double Value = 0;
G4double Gradient = 0;
G4double Lambda ;
G4int i=0;
/* Reduce interval before applying Newton Method */
#if DEBUGTORUS
G4cout << "G4Torus::Newton Lmin = " << Lmin
<< " Lmax = " << Lmax << G4endl ;
break;
#endif
default:
G4cerr << "G4Torus::DistanceToTorus NbIntersection = " << NbIntersection << G4endl;
break;
}
TorusEquationClass torus (Rmax,Rmin);
torus.setPosition(x,y,z);
torus.setDirection(dx,dy,dz);
{
G4int NewtonIsSafe ;
G4int k;
/*
Here we stop to compute after ITERATION loop
*/
for (k=0;
((k<ITERATION) &&
((NewtonIsSafe = SafeNewton(x,y,z,dx,dy,dz,Rmax,Rmin,&Lmin,&Lmax))==0));
k++);
G4PolynomialSolver<TorusEquationClass,G4double(TorusEquationClass::*)(G4double)>
PolySolver(&torus,
&TorusEquationClass::Function,
&TorusEquationClass::Derivative,
TORUSPRECISION) ;
/* But in fact it is safer to compute while this is safe
while ((NewtonIsSafe = SafeNewton(x,y,z,dx,dy,dz,Rmax,Rmin,&Lmin,&Lmax)) == 0) ;
guess = PolySolver.solve(Lmin,Lmax);
Problem: the mathematical algorithm is the one with the while loop
but because of precision issue we could have TorusEquation(point) never equal to zero..
But we see that all initial points are on the bounding volume. So there is a superior limit
to the number of iteration in the while loop to reach the point with the given precision.
*/
guess = Lmin;
}
/** So with SafeNewton we do not need a guess **/
Lambda = guess;
Value = TorusEquation(x + Lambda*dx,y + Lambda*dy,z + Lambda*dz,Rmax,Rmin);
//If we want a gnuplot graphics af the function
#if 0
{
FILE *fi;
G4int i;
fi = fopen("GNUplot.out","w+");
fprintf(fi,"# Newton plot\n");
for (i = 0; i < 1000 ; i ++) {
Lx = x + (Lmin + i*(Lmax - Lmin)/1000.0)*dx;
Ly = y + (Lmin + i*(Lmax - Lmin)/1000.0)*dy;
Lz = z + (Lmin + i*(Lmax - Lmin)/1000.0)*dz;
Value = TorusEquation(Lx,Ly,Lz,Rmax,Rmin);
fprintf(fi," %f %f\n",Lmin + i*(Lmax - Lmin)/1000.0,Value );
}
fclose(fi);
}
#endif
/* In fact The Torus Equation give big number
so TORUS PRECISION is not EPSILON */
while (fabs(Value) > TORUSPRECISION) {
Lx = x + Lambda*dx;
Ly = y + Lambda*dy;
Lz = z + Lambda*dz;
Value = TorusEquation(Lx,Ly,Lz,Rmax,Rmin);
Gradient = dx*TorusDerivativeX(Lx,Ly,Lz,Rmax,Rmin);
Gradient += dy*TorusDerivativeY(Lx,Ly,Lz,Rmax,Rmin);
Gradient += dz*TorusDerivativeZ(Lx,Ly,Lz,Rmax,Rmin);
/**
if (Gradient > -EPSILON) { // then the current point is repulsive
and may not converge
Seems to be solved by SafeNewton
**/
Lambda = Lambda - Value/Gradient ;
if ((guess >= (Lmin - POLEPSILON)) && (guess <= (Lmax + POLEPSILON))) {
#if DEBUGTORUS
G4cout << "G4Torus::Newton Iteration " << i << G4endl ;
G4cout << "G4Torus::Newton Lambda = " << Lambda
<< " Value = " << Value << " Grad = " << Gradient << G4endl;
G4cout << "G4Torus::Newton Lmin = " << Lmin
<< " Lmax = " << Lmax << G4endl ;
G4cout << "G4Torus::DistanceToTorus distance = " << guess << G4endl ;
#endif
i ++;
if (i > ITERATION)
return NOINTERSECTION; //no convergency ??
}
#if DEBUGTORUS
G4cout << "G4Torus::Newton Exiting with Lambda = " << Lambda << G4endl ;
G4cout << "G4Torus::Newton Exiting with Value = " << Value << G4endl ;
if (Gradient > 0.0) {
G4cout << "G4Torus::Newton Gradient: Exiting surface" << G4endl ;
return guess ;
} else {
G4cout << "G4Torus::Newton Gradient: Entering surface" << G4endl ;
}
#if DEBUGTORUS
G4cout << "G4Torus::DistanceToTorus : kInfinity" << G4endl ;
#endif
return Lambda ;
return kInfinity;
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4Trap.cc,v 1.8 2000/11/20 17:58:01 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// GEANT4 tag $Name: geant4-03-01 $
//
// class G4Trap
//
+1 -1
View File
@@ -6,7 +6,7 @@
// and all its terms.
//
// $Id: G4Trd.cc,v 1.7 2000/11/20 17:58:01 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-00 $
// GEANT4 tag $Name: geant4-03-01 $
//
//
// Implementation for G4Trd class
+53 -26
View File
@@ -5,8 +5,8 @@
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4Tubs.cc,v 1.23 2000/11/28 15:05:52 grichine Exp $
// GEANT4 tag $Name: geant4-03-00 $
// $Id: G4Tubs.cc,v 1.28 2001/02/21 15:47:14 gcosmo Exp $
// GEANT4 tag $Name: geant4-03-01 $
//
//
// class G4Tubs
@@ -28,6 +28,9 @@
// 08.08.00 V.Grichine, more stable roots of 2-equation in Distance ToOut(p,v,...)
// 31.10.00 V.Grichine, assign sr, sphi in Distance ToOut(p,v,...)
// 28.11.00 V.Grichine, bug fixed in Inside(p)
// 07.12.00 V.Grichine, phi-section algorithm was changed in Inside(p)
// 20.02.01 V.Grichine, bug fixed in Inside(p) and CalculateExtent was
// simplified base on G4Box::CalculateExtent
#include "G4Tubs.hh"
@@ -44,6 +47,7 @@
#include "G4NURBStube.hh"
#include "G4NURBScylinder.hh"
#include "G4NURBStubesector.hh"
#include "G4Box.hh"
/////////////////////////////////////////////////////////////////////////
//
@@ -139,6 +143,9 @@ G4bool G4Tubs::CalculateExtent( const EAxis pAxis,
G4double& pMin,
G4double& pMax ) const
{
G4Box box("box",fRMax,fRMax,fDz) ;
return box.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax) ;
/*
if ( !pTransform.IsRotated() && fDPhi == 2.0*M_PI && fRMin == 0 )
{
// Special case handling for unrotated solid tubes
@@ -324,8 +331,10 @@ G4bool G4Tubs::CalculateExtent( const EAxis pAxis,
delete vertices;
return existsAfterClip;
}
*/
}
///////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface
@@ -354,25 +363,32 @@ EInside G4Tubs::Inside(const G4ThreeVector& p) const
pPhi = atan2(p.y(),p.x()) ;
if ( pPhi < 0 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi
if ( pPhi < -kAngTolerance*0.5 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi
if ( fSPhi >= 0 )
{
if ( abs(pPhi) < kAngTolerance*0.5 &&
abs(fSPhi + fDPhi - 2*M_PI) < kAngTolerance*0.5 )
{
pPhi += 2*M_PI ; // 0 <= pPhi < 2pi
}
if ( pPhi >= fSPhi + kAngTolerance*0.5 &&
pPhi <= fSPhi + fDPhi-kAngTolerance*0.5 ) in = kInside ;
pPhi <= fSPhi + fDPhi - kAngTolerance*0.5 ) in = kInside ;
else if ( pPhi >= fSPhi - kAngTolerance*0.5 &&
pPhi <= fSPhi + fDPhi + kAngTolerance*0.5 ) in = kSurface ;
}
else
else // fSPhi < 0
{
// if (pPhi < fSPhi + 2*M_PI) pPhi += 2*M_PI ;
if ( pPhi <= fSPhi + 2*M_PI - kAngTolerance*0.5 &&
pPhi >= fSPhi + fDPhi + kAngTolerance*0.5) ;
if ( pPhi >= fSPhi + 2*M_PI + kAngTolerance*0.5 &&
pPhi <= fSPhi + fDPhi + 2*M_PI - kAngTolerance*0.5) in = kInside ;
else if ( pPhi <= fSPhi + 2*M_PI + kAngTolerance*0.5 &&
pPhi >= fSPhi + fDPhi - kAngTolerance*0.5) in = kSurface ;
else if (pPhi >= fSPhi+2*M_PI-kAngTolerance*0.5 &&
pPhi <= fSPhi+fDPhi+2*M_PI+kAngTolerance*0.5) in = kSurface ;
else in = kInside ;
}
}
}
@@ -393,25 +409,30 @@ EInside G4Tubs::Inside(const G4ThreeVector& p) const
{
pPhi = atan2(p.y(),p.x()) ;
if ( pPhi < 0 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi
if ( pPhi < -kAngTolerance*0.5 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi
if ( fSPhi >= 0 )
{
if (pPhi >= fSPhi-kAngTolerance*0.5 &&
pPhi <= fSPhi+fDPhi+kAngTolerance*0.5) in = kSurface ;
if ( abs(pPhi) < kAngTolerance*0.5 &&
abs(fSPhi + fDPhi - 2*M_PI) < kAngTolerance*0.5 )
{
pPhi += 2*M_PI ; // 0 <= pPhi < 2pi
}
if ( pPhi >= fSPhi - kAngTolerance*0.5 &&
pPhi <= fSPhi + fDPhi + kAngTolerance*0.5) in = kSurface ;
}
else
else // fSPhi < 0
{
// if (pPhi < fSPhi + 2*M_PI ) pPhi += 2*M_PI ;
if ( pPhi <= fSPhi + 2*M_PI - kAngTolerance*0.5 &&
pPhi >= fSPhi + fDPhi + kAngTolerance*0.5) ;
if (pPhi >= fSPhi+2*M_PI-kAngTolerance*0.5 &&
pPhi <= fSPhi+fDPhi+2*M_PI+kAngTolerance*0.5) in=kSurface;
else in = kSurface ;
}
}
}
}
}
else if (fabs(p.z()) <= fDz+kCarTolerance*0.5) // Check within tolerant r limits
else if (fabs(p.z()) <= fDz + kCarTolerance*0.5) // Check within tolerant r limits
{
r2 = p.x()*p.x() + p.y()*p.y() ;
tolRMin = fRMin - kRadTolerance*0.5 ;
@@ -429,19 +450,23 @@ EInside G4Tubs::Inside(const G4ThreeVector& p) const
{
pPhi = atan2(p.y(),p.x()) ;
if ( pPhi < 0 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi
if ( pPhi < -kAngTolerance*0.5 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi
if ( fSPhi >= 0 )
{
if (pPhi >= fSPhi-kAngTolerance*0.5 &&
pPhi <= fSPhi+fDPhi+kAngTolerance*0.5) in=kSurface;
if ( abs(pPhi) < kAngTolerance*0.5 &&
abs(fSPhi + fDPhi - 2*M_PI) < kAngTolerance*0.5 )
{
pPhi += 2*M_PI ; // 0 <= pPhi < 2pi
}
if ( pPhi >= fSPhi - kAngTolerance*0.5 &&
pPhi <= fSPhi + fDPhi + kAngTolerance*0.5) in = kSurface;
}
else
else // fSPhi < 0
{
if ( pPhi < fSPhi + 2*M_PI ) pPhi += 2*M_PI ;
if ( pPhi >= fSPhi+2*M_PI-kAngTolerance*0.5 &&
pPhi <= fSPhi+fDPhi+2*M_PI+kAngTolerance*0.5) in = kSurface ;
if ( pPhi <= fSPhi + 2*M_PI - kAngTolerance*0.5 &&
pPhi >= fSPhi + fDPhi + kAngTolerance*0.5) ;
else in = kSurface ;
}
}
}
@@ -449,6 +474,8 @@ EInside G4Tubs::Inside(const G4ThreeVector& p) const
return in ;
}
///////////////////////////////////////////////////////////////////////////
//
// Return unit normal of surface closest to p