Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Paraboloid Class Reference

G4Paraboloid represents a solid with parabolic profile with possible cuts along the Z axis. More...

#include <G4Paraboloid.hh>

Inheritance diagram for G4Paraboloid:

Public Member Functions

 G4Paraboloid (const G4String &pName, G4double pDz, G4double pR1, G4double pR2)
 ~G4Paraboloid () override
G4double GetZHalfLength () const
G4double GetRadiusMinusZ () const
G4double GetRadiusPlusZ () const
void SetZHalfLength (G4double dz)
void SetRadiusMinusZ (G4double R1)
void SetRadiusPlusZ (G4double R2)
void BoundingLimits (G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
EInside Inside (const G4ThreeVector &p) const override
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const override
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double DistanceToIn (const G4ThreeVector &p) const override
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double DistanceToOut (const G4ThreeVector &p) const override
G4GeometryType GetEntityType () const override
G4VSolidClone () const override
std::ostream & StreamInfo (std::ostream &os) const override
G4double GetCubicVolume () override
G4double GetSurfaceArea () override
G4ThreeVector GetPointOnSurface () const override
void DescribeYourselfTo (G4VGraphicsScene &scene) const override
G4PolyhedronCreatePolyhedron () const override
G4PolyhedronGetPolyhedron () const override
 G4Paraboloid (__void__ &)
 G4Paraboloid (const G4Paraboloid &rhs)
G4Paraboloidoperator= (const G4Paraboloid &rhs)
Public Member Functions inherited from G4VSolid
 G4VSolid (const G4String &name)
virtual ~G4VSolid ()
 G4VSolid (const G4VSolid &rhs)
G4VSolidoperator= (const G4VSolid &rhs)
G4bool operator== (const G4VSolid &s) const
G4String GetName () const
void SetName (const G4String &name)
G4double GetTolerance () const
virtual void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
virtual G4int GetNumOfConstituents () const
virtual G4bool IsFaceted () const
void DumpInfo () const
virtual G4VisExtent GetExtent () const
virtual const G4VSolidGetConstituentSolid (G4int no) const
virtual G4VSolidGetConstituentSolid (G4int no)
virtual const G4DisplacedSolidGetDisplacedSolidPtr () const
virtual G4DisplacedSolidGetDisplacedSolidPtr ()
 G4VSolid (__void__ &)
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
G4double EstimateSurfaceArea (G4int nStat, G4double epsilon) const

Additional Inherited Members

Protected Member Functions inherited from G4VSolid
void CalculateClippedPolygonExtent (G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
void ClipCrossSection (G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
void ClipBetweenSections (G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
void ClipPolygon (G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis) const
Protected Attributes inherited from G4VSolid
G4double kCarTolerance

Detailed Description

G4Paraboloid represents a solid with parabolic profile with possible cuts along the Z axis.

Definition at line 71 of file G4Paraboloid.hh.

Constructor & Destructor Documentation

◆ G4Paraboloid() [1/3]

G4Paraboloid::G4Paraboloid ( const G4String & pName,
G4double pDz,
G4double pR1,
G4double pR2 )

Constructs a paraboloid, given its parameters.

Parameters
[in]pNameThe solid name.
[in]pDzHalf length in Z.
[in]pR1Radius at -Dz.
[in]pR2Radius at +Dz greater than pR1.

Definition at line 60 of file G4Paraboloid.cc.

64 : G4VSolid(pName)
65{
66 if( (pDz <= 0.) || (pR2 <= pR1) || (pR1 < 0.) )
67 {
68 std::ostringstream message;
69 message << "Invalid dimensions. Negative Input Values or R1>=R2 - "
70 << GetName();
71 G4Exception("G4Paraboloid::G4Paraboloid()", "GeomSolids0002",
72 FatalErrorInArgument, message,
73 "Z half-length must be larger than zero or R1>=R2.");
74 }
75
76 r1 = pR1;
77 r2 = pR2;
78 dz = pDz;
79
80 // r1^2 = k1 * (-dz) + k2
81 // r2^2 = k1 * ( dz) + k2
82 // => r1^2 + r2^2 = k2 + k2 => k2 = (r2^2 + r1^2) / 2
83 // and r2^2 - r1^2 = k1 * dz - k1 * (-dz) => k1 = (r2^2 - r1^2) / 2 / dz
84
85 k1 = (r2 * r2 - r1 * r1) / 2 / dz;
86 k2 = (r2 * r2 + r1 * r1) / 2;
87
88 fSurfaceArea = CalculateSurfaceArea();
89}
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4String GetName() const
G4VSolid(const G4String &name)
Definition G4VSolid.cc:59

Referenced by Clone(), G4Paraboloid(), GetRadiusPlusZ(), and operator=().

◆ ~G4Paraboloid()

G4Paraboloid::~G4Paraboloid ( )
override

Destructor.

Definition at line 105 of file G4Paraboloid.cc.

106{
107 delete fpPolyhedron; fpPolyhedron = nullptr;
108}

◆ G4Paraboloid() [2/3]

G4Paraboloid::G4Paraboloid ( __void__ & a)

Fake default constructor for usage restricted to direct object persistency for clients requiring preallocation of memory for persistifiable objects.

Definition at line 96 of file G4Paraboloid.cc.

97 : G4VSolid(a)
98{
99}

◆ G4Paraboloid() [3/3]

G4Paraboloid::G4Paraboloid ( const G4Paraboloid & rhs)

Copy constructor and assignment operator.

Definition at line 114 of file G4Paraboloid.cc.

115 : G4VSolid(rhs),
116 fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume),
117 dz(rhs.dz), r1(rhs.r1), r2(rhs.r2), k1(rhs.k1), k2(rhs.k2)
118{
119}

Member Function Documentation

◆ BoundingLimits()

void G4Paraboloid::BoundingLimits ( G4ThreeVector & pMin,
G4ThreeVector & pMax ) const
overridevirtual

Computes the bounding limits of the solid.

Parameters
[out]pMinThe minimum bounding limit point.
[out]pMaxThe maximum bounding limit point.

Reimplemented from G4VSolid.

Definition at line 270 of file G4Paraboloid.cc.

272{
273 pMin.set(-r2,-r2,-dz);
274 pMax.set( r2, r2, dz);
275
276 // Check correctness of the bounding box
277 //
278 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
279 {
280 std::ostringstream message;
281 message << "Bad bounding box (min >= max) for solid: "
282 << GetName() << " !"
283 << "\npMin = " << pMin
284 << "\npMax = " << pMax;
285 G4Exception("G4Paraboloid::BoundingLimits()", "GeomMgt0001",
286 JustWarning, message);
287 DumpInfo();
288 }
289}
@ JustWarning
double z() const
double x() const
double y() const
void set(double x, double y, double z)
void DumpInfo() const

Referenced by CalculateExtent().

◆ CalculateExtent()

G4bool G4Paraboloid::CalculateExtent ( const EAxis pAxis,
const G4VoxelLimits & pVoxelLimit,
const G4AffineTransform & pTransform,
G4double & pmin,
G4double & pmax ) const
overridevirtual

Calculates the minimum and maximum extent of the solid, when under the specified transform, and within the specified limits.

Parameters
[in]pAxisThe axis along which compute the extent.
[in]pVoxelLimitThe limiting space dictated by voxels.
[in]pTransformThe internal transformation applied to the solid.
[out]pMinThe minimum extent value.
[out]pMaxThe maximum extent value.
Returns
True if the solid is intersected by the extent region.

Implements G4VSolid.

Definition at line 296 of file G4Paraboloid.cc.

300{
301 G4ThreeVector bmin, bmax;
302
303 // Get bounding box
304 BoundingLimits(bmin,bmax);
305
306 // Find extent
307 G4BoundingEnvelope bbox(bmin,bmax);
308 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
309}
CLHEP::Hep3Vector G4ThreeVector
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override

◆ Clone()

G4VSolid * G4Paraboloid::Clone ( ) const
overridevirtual

Makes a clone of the object for use in multi-treading.

Returns
A pointer to the new cloned allocated solid.

Reimplemented from G4VSolid.

Definition at line 954 of file G4Paraboloid.cc.

955{
956 return new G4Paraboloid(*this);
957}
G4Paraboloid(const G4String &pName, G4double pDz, G4double pR1, G4double pR2)

◆ CreatePolyhedron()

G4Polyhedron * G4Paraboloid::CreatePolyhedron ( ) const
overridevirtual

Creates a Polyhedron used for Visualisation. It is the caller's responsibility to delete it. A null pointer means "not created".

Reimplemented from G4VSolid.

Definition at line 1026 of file G4Paraboloid.cc.

1027{
1028 return new G4PolyhedronParaboloid(r1, r2, dz, 0., twopi);
1029}

Referenced by GetPolyhedron().

◆ DescribeYourselfTo()

void G4Paraboloid::DescribeYourselfTo ( G4VGraphicsScene & scene) const
overridevirtual

Methods for creating graphical representations (i.e. for visualisation).

Implements G4VSolid.

Definition at line 1021 of file G4Paraboloid.cc.

1022{
1023 scene.AddSolid(*this);
1024}
virtual void AddSolid(const G4Box &)=0

◆ DistanceToIn() [1/2]

G4double G4Paraboloid::DistanceToIn ( const G4ThreeVector & p) const
overridevirtual

Calculates the distance to the nearest surface of a shape from an outside point. The distance can be an underestimate.

Parameters
[in]pThe point at offset p.
Returns
The safety distance to enter the shape.

Implements G4VSolid.

Definition at line 561 of file G4Paraboloid.cc.

562{
563 G4double safz = -dz+std::fabs(p.z());
564 if(safz<0.) { safz=0.; }
565 G4double safr = kInfinity;
566
567 G4double rho = p.x()*p.x()+p.y()*p.y();
568 G4double paraRho = (p.z()-k2)/k1;
569 G4double sqrho = std::sqrt(rho);
570
571 if(paraRho<0.)
572 {
573 safr=sqrho-r2;
574 if(safr>safz) { safz=safr; }
575 return safz;
576 }
577
578 G4double sqprho = std::sqrt(paraRho);
579 G4double dRho = sqrho-sqprho;
580 if(dRho<0.) { return safz; }
581
582 G4double talf = -2.*k1*sqprho;
583 G4double tmp = 1+talf*talf;
584 if(tmp<0.) { return safz; }
585
586 G4double salf = talf/std::sqrt(tmp);
587 safr = std::fabs(dRho*salf);
588 if(safr>safz) { safz=safr; }
589
590 return safz;
591}
double G4double
Definition G4Types.hh:83

◆ DistanceToIn() [2/2]

G4double G4Paraboloid::DistanceToIn ( const G4ThreeVector & p,
const G4ThreeVector & v ) const
overridevirtual

Returns the distance along the normalised vector 'v' to the shape, from the point at offset 'p'. If there is no intersection, returns kInfinity. The first intersection resulting from 'leaving' a surface/volume is discarded. Hence, it is tolerant of points on the surface of the shape.

Parameters
[in]pThe point at offset p.
[in]vThe normalised direction vector.
Returns
The distance to enter the shape.

Implements G4VSolid.

Definition at line 447 of file G4Paraboloid.cc.

449{
450 G4double rho2 = p.perp2(), paraRho2 = std::fabs(k1 * p.z() + k2);
452 G4double tolh = 0.5*kCarTolerance;
453
454 if((r2 != 0.0) && p.z() > - tolh + dz)
455 {
456 // If the points is above check for intersection with upper edge.
457
458 if(v.z() < 0)
459 {
460 G4double intersection = (dz - p.z()) / v.z(); // With plane z = dz.
461 if(sqr(p.x() + v.x()*intersection)
462 + sqr(p.y() + v.y()*intersection) < sqr(r2 + 0.5 * kCarTolerance))
463 {
464 if(p.z() < tolh + dz) { return 0; }
465 return intersection;
466 }
467 }
468 else // Direction away, no possibility of intersection
469 {
470 return kInfinity;
471 }
472 }
473 else if((r1 != 0.0) && p.z() < tolh - dz)
474 {
475 // If the points is belove check for intersection with lower edge.
476
477 if(v.z() > 0)
478 {
479 G4double intersection = (-dz - p.z()) / v.z(); // With plane z = -dz.
480 if(sqr(p.x() + v.x()*intersection)
481 + sqr(p.y() + v.y()*intersection) < sqr(r1 + 0.5 * kCarTolerance))
482 {
483 if(p.z() > -tolh - dz) { return 0; }
484 return intersection;
485 }
486 }
487 else // Direction away, no possibility of intersection
488 {
489 return kInfinity;
490 }
491 }
492
493 G4double A = k1 / 2 * v.z() - p.x() * v.x() - p.y() * v.y(),
494 vRho2 = v.perp2(), intersection,
495 B = (k1 * p.z() + k2 - rho2) * vRho2;
496
497 if ( ( (rho2 > paraRho2) && (sqr(rho2-paraRho2-0.25*tol2) > tol2*paraRho2) )
498 || (p.z() < - dz+kCarTolerance)
499 || (p.z() > dz-kCarTolerance) ) // Make sure it's safely outside.
500 {
501 // Is there a problem with squaring rho twice?
502
503 if(vRho2<tol2) // Needs to be treated separately.
504 {
505 intersection = ((rho2 - k2)/k1 - p.z())/v.z();
506 if(intersection < 0) { return kInfinity; }
507 if(std::fabs(p.z() + v.z() * intersection) <= dz) { return intersection; }
508 return kInfinity;
509 }
510
511 if(A*A + B < 0) // No real intersections.
512 {
513 return kInfinity;
514 }
515
516 intersection = (A - std::sqrt(B + sqr(A))) / vRho2;
517 if(intersection < 0)
518 {
519 return kInfinity;
520 }
521
522 if(std::fabs(p.z() + intersection * v.z()) < dz + tolh)
523 {
524 return intersection;
525 }
526
527 return kInfinity;
528 }
529 if(sqr(rho2 - paraRho2 - .25 * tol2) <= tol2 * paraRho2)
530 {
531 // If this is true we're somewhere in the border.
532
533 G4ThreeVector normal(p.x(), p.y(), -k1/2);
534 if(normal.dot(v) <= 0) { return 0; }
535
536 return kInfinity;
537 }
538
539 std::ostringstream message;
540 if(Inside(p) == kInside)
541 {
542 message << "Point p is inside! - " << GetName() << G4endl;
543 }
544 else
545 {
546 message << "Likely a problem in this function, for solid: " << GetName()
547 << G4endl;
548 }
549 message << " p = " << p * (1/mm) << " mm" << G4endl
550 << " v = " << v * (1/mm) << " mm";
551 G4Exception("G4Paraboloid::DistanceToIn(p,v)", "GeomSolids1002",
552 JustWarning, message);
553 return 0;
554}
G4double B(G4double temperature)
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
double perp2() const
EInside Inside(const G4ThreeVector &p) const override
G4double kCarTolerance
Definition G4VSolid.hh:418
@ kInside
Definition geomdefs.hh:70
T sqr(const T &x)
Definition templates.hh:128

◆ DistanceToOut() [1/2]

G4double G4Paraboloid::DistanceToOut ( const G4ThreeVector & p) const
overridevirtual

Calculates the distance to the nearest surface of a shape from an inside point 'p'. The distance can be an underestimate.

Parameters
[in]pThe point at offset p.
Returns
The safety distance to exit the shape.

Implements G4VSolid.

Definition at line 904 of file G4Paraboloid.cc.

905{
906 G4double safe=0.0,rho,safeR,safeZ ;
907 G4double tanRMax,secRMax,pRMax ;
908
909#ifdef G4SPECSDEBUG
910 if( Inside(p) == kOutside )
911 {
912 G4cout << G4endl ;
913 DumpInfo();
914 std::ostringstream message;
915 G4long oldprc = message.precision(16);
916 message << "Point p is outside !?" << G4endl
917 << "Position:" << G4endl
918 << " p.x() = " << p.x()/mm << " mm" << G4endl
919 << " p.y() = " << p.y()/mm << " mm" << G4endl
920 << " p.z() = " << p.z()/mm << " mm";
921 message.precision(oldprc) ;
922 G4Exception("G4Paraboloid::DistanceToOut(p)", "GeomSolids1002",
923 JustWarning, message);
924 }
925#endif
926
927 rho = p.perp();
928 safeZ = dz - std::fabs(p.z()) ;
929
930 tanRMax = (r2 - r1)*0.5/dz ;
931 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
932 pRMax = tanRMax*p.z() + (r1+r2)*0.5 ;
933 safeR = (pRMax - rho)/secRMax ;
934
935 if (safeZ < safeR) { safe = safeZ; }
936 else { safe = safeR; }
937 if ( safe < 0.5 * kCarTolerance ) { safe = 0; }
938 return safe ;
939}
long G4long
Definition G4Types.hh:87
G4GLOB_DLL std::ostream G4cout
double perp() const
@ kOutside
Definition geomdefs.hh:68

◆ DistanceToOut() [2/2]

G4double G4Paraboloid::DistanceToOut ( const G4ThreeVector & p,
const G4ThreeVector & v,
const G4bool calcNorm = false,
G4bool * validNorm = nullptr,
G4ThreeVector * n = nullptr ) const
overridevirtual

Returns the 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 less than Tolerance/2 from a surface must be ignored.

Parameters
[in]pThe point at offset p.
[in]vThe normalised direction vector.
[in]calcNormFlag to indicate if to calculate the normal or not.
[out]validNormFlag set to true if the solid lies entirely behind or on the exiting surface. It is set false if the solid does not lie entirely behind or on the exiting surface. 'calcNorm' must be true, otherwise it is unused.
[out]nThe exiting outwards normal vector (undefined Magnitude). 'calcNorm' must be true, otherwise it is unused.
Returns
The distance to exit the shape.

Implements G4VSolid.

Definition at line 597 of file G4Paraboloid.cc.

602{
603 G4double rho2 = p.perp2(), paraRho2 = std::fabs(k1 * p.z() + k2);
604 G4double vRho2 = v.perp2(), intersection;
606 G4double tolh = 0.5*kCarTolerance;
607
608 if(calcNorm) { *validNorm = false; }
609
610 // We have that the particle p follows the line x = p + s * v
611 // meaning x = p.x() + s * v.x(), y = p.y() + s * v.y() and
612 // z = p.z() + s * v.z()
613 // The equation for all points on the surface (surface expanded for
614 // to include all z) x^2 + y^2 = k1 * z + k2 => .. =>
615 // => s = (A +- std::sqrt(A^2 + B)) / vRho2
616 // where:
617 //
618 G4double A = k1 / 2 * v.z() - p.x() * v.x() - p.y() * v.y();
619 //
620 // and:
621 //
622 G4double B = (-rho2 + paraRho2) * vRho2;
623
624 if ( rho2 < paraRho2 && sqr(rho2 - paraRho2 - 0.25 * tol2) > tol2 * paraRho2
625 && std::fabs(p.z()) < dz - kCarTolerance)
626 {
627 // Make sure it's safely inside.
628
629 if(v.z() > 0)
630 {
631 // It's heading upwards, check where it colides with the plane z = dz.
632 // When it does, is that in the surface of the paraboloid.
633 // z = p.z() + variable * v.z() for all points the particle can go.
634 // => variable = (z - p.z()) / v.z() so intersection must be:
635
636 intersection = (dz - p.z()) / v.z();
637 G4ThreeVector ip = p + intersection * v; // Point of intersection.
638
639 if(ip.perp2() < sqr(r2 + kCarTolerance))
640 {
641 if(calcNorm)
642 {
643 *n = G4ThreeVector(0, 0, 1);
644 if(r2 < tolh || ip.perp2() > sqr(r2 - tolh))
645 {
646 *n += G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
647 *n = n->unit();
648 }
649 *validNorm = true;
650 }
651 return intersection;
652 }
653 }
654 else if(v.z() < 0)
655 {
656 // It's heading downwards, check were it colides with the plane z = -dz.
657 // When it does, is that in the surface of the paraboloid.
658 // z = p.z() + variable * v.z() for all points the particle can go.
659 // => variable = (z - p.z()) / v.z() so intersection must be:
660
661 intersection = (-dz - p.z()) / v.z();
662 G4ThreeVector ip = p + intersection * v; // Point of intersection.
663
664 if(ip.perp2() < sqr(r1 + tolh))
665 {
666 if(calcNorm)
667 {
668 *n = G4ThreeVector(0, 0, -1);
669 if(r1 < tolh || ip.perp2() > sqr(r1 - tolh))
670 {
671 *n += G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
672 *n = n->unit();
673 }
674 *validNorm = true;
675 }
676 return intersection;
677 }
678 }
679
680 // Now check for collisions with paraboloid surface.
681
682 if(vRho2 == 0) // Needs to be treated seperately.
683 {
684 intersection = ((rho2 - k2)/k1 - p.z())/v.z();
685 if(calcNorm)
686 {
687 G4ThreeVector intersectionP = p + v * intersection;
688 *n = G4ThreeVector(intersectionP.x(), intersectionP.y(), -k1/2);
689 *n = n->unit();
690
691 *validNorm = true;
692 }
693 return intersection;
694 }
695 if( ((A <= 0) && (B >= sqr(A) * (sqr(vRho2) - 1))) || (A >= 0))
696 {
697 // intersection = (A + std::sqrt(B + sqr(A))) / vRho2;
698 // The above calculation has a precision problem:
699 // known problem of solving quadratic equation with small A
700
701 A = A/vRho2;
702 B = (k1 * p.z() + k2 - rho2)/vRho2;
703 intersection = B/(-A + std::sqrt(B + sqr(A)));
704 if(calcNorm)
705 {
706 G4ThreeVector intersectionP = p + v * intersection;
707 *n = G4ThreeVector(intersectionP.x(), intersectionP.y(), -k1/2);
708 *n = n->unit();
709 *validNorm = true;
710 }
711 return intersection;
712 }
713 std::ostringstream message;
714 message << "There is no intersection between given line and solid!"
715 << G4endl
716 << " p = " << p << G4endl
717 << " v = " << v;
718 G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
719 JustWarning, message);
720
721 return kInfinity;
722 }
723 if ( (rho2 < paraRho2 + kCarTolerance
724 || sqr(rho2 - paraRho2 - 0.25 * tol2) < tol2 * paraRho2 )
725 && std::fabs(p.z()) < dz + tolh)
726 {
727 // If this is true we're somewhere in the border.
728
729 G4ThreeVector normal = G4ThreeVector (p.x(), p.y(), -k1/2);
730
731 if(std::fabs(p.z()) > dz - tolh)
732 {
733 // We're in the lower or upper edge
734 //
735 if( ((v.z() > 0) && (p.z() > 0)) || ((v.z() < 0) && (p.z() < 0)) )
736 { // If we're heading out of the object that is treated here
737 if(calcNorm)
738 {
739 *validNorm = true;
740 if(p.z() > 0)
741 { *n = G4ThreeVector(0, 0, 1); }
742 else
743 { *n = G4ThreeVector(0, 0, -1); }
744 }
745 return 0;
746 }
747
748 if(v.z() == 0)
749 {
750 // Case where we're moving inside the surface needs to be
751 // treated separately.
752 // Distance until it goes out through a side is returned.
753
754 G4double r = (p.z() > 0)? r2 : r1;
755 G4double pDotV = p.dot(v);
756 A = vRho2 * ( sqr(r) - sqr(p.x()) - sqr(p.y()));
757 intersection = (-pDotV + std::sqrt(A + sqr(pDotV))) / vRho2;
758
759 if(calcNorm)
760 {
761 *validNorm = true;
762
763 *n = (G4ThreeVector(0, 0, p.z()/std::fabs(p.z()))
764 + G4ThreeVector(p.x() + v.x() * intersection, p.y() + v.y()
765 * intersection, -k1/2).unit()).unit();
766 }
767 return intersection;
768 }
769 }
770 //
771 // Problem in the Logic :: Following condition for point on upper surface
772 // and Vz<0 will return 0 (Problem #1015), but
773 // it has to return intersection with parabolic
774 // surface or with lower plane surface (z = -dz)
775 // The logic has to be :: If not found intersection until now,
776 // do not exit but continue to search for possible intersection.
777 // Only for point situated on both borders (Z and parabolic)
778 // this condition has to be taken into account and done later
779 //
780 //
781 // else if(normal.dot(v) >= 0)
782 // {
783 // if(calcNorm)
784 // {
785 // *validNorm = true;
786 // *n = normal.unit();
787 // }
788 // return 0;
789 // }
790
791 if(v.z() > 0)
792 {
793 // Check for collision with upper edge.
794
795 intersection = (dz - p.z()) / v.z();
796 G4ThreeVector ip = p + intersection * v;
797
798 if(ip.perp2() < sqr(r2 - tolh))
799 {
800 if(calcNorm)
801 {
802 *validNorm = true;
803 *n = G4ThreeVector(0, 0, 1);
804 }
805 return intersection;
806 }
807 if(ip.perp2() < sqr(r2 + tolh))
808 {
809 if(calcNorm)
810 {
811 *validNorm = true;
812 *n = G4ThreeVector(0, 0, 1)
813 + G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
814 *n = n->unit();
815 }
816 return intersection;
817 }
818 }
819 if( v.z() < 0)
820 {
821 // Check for collision with lower edge.
822
823 intersection = (-dz - p.z()) / v.z();
824 G4ThreeVector ip = p + intersection * v;
825
826 if(ip.perp2() < sqr(r1 - tolh))
827 {
828 if(calcNorm)
829 {
830 *validNorm = true;
831 *n = G4ThreeVector(0, 0, -1);
832 }
833 return intersection;
834 }
835 if(ip.perp2() < sqr(r1 + tolh))
836 {
837 if(calcNorm)
838 {
839 *validNorm = true;
840 *n = G4ThreeVector(0, 0, -1)
841 + G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
842 *n = n->unit();
843 }
844 return intersection;
845 }
846 }
847
848 // Note: comparison with zero below would not be correct !
849 //
850 if(std::fabs(vRho2) > tol2) // precision error in the calculation of
851 { // intersection = (A+std::sqrt(B+sqr(A)))/vRho2
852 A = A/vRho2;
853 B = (k1 * p.z() + k2 - rho2);
854 if(std::fabs(B)>kCarTolerance)
855 {
856 B = (B)/vRho2;
857 intersection = B/(-A + std::sqrt(B + sqr(A)));
858 }
859 else // Point is On both borders: Z and parabolic
860 { // solution depends on normal.dot(v) sign
861 if(normal.dot(v) >= 0)
862 {
863 if(calcNorm)
864 {
865 *validNorm = true;
866 *n = normal.unit();
867 }
868 return 0;
869 }
870 intersection = 2.*A;
871 }
872 }
873 else
874 {
875 intersection = ((rho2 - k2) / k1 - p.z()) / v.z();
876 }
877
878 if(calcNorm)
879 {
880 *validNorm = true;
881 *n = G4ThreeVector(p.x() + intersection * v.x(), p.y()
882 + intersection * v.y(), - k1 / 2);
883 *n = n->unit();
884 }
885 return intersection;
886 }
887
888#ifdef G4SPECSDEBUG
889 if(kOutside == Inside(p))
890 {
891 G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
892 JustWarning, "Point p is outside!");
893 }
894 G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
895 JustWarning, "There's an error in this functions code.");
896#endif
897 return kInfinity;
898}
Hep3Vector unit() const
double dot(const Hep3Vector &) const

◆ GetCubicVolume()

G4double G4Paraboloid::GetCubicVolume ( )
overridevirtual

Returning an estimation of the solid volume (capacity) and surface area, in internal units.

Reimplemented from G4VSolid.

Definition at line 255 of file G4Paraboloid.cc.

256{
257 if(fCubicVolume == 0)
258 {
259 G4AutoLock l(&paraboloidMutex);
260 fCubicVolume = CLHEP::pi * (sqr(r1) + sqr(r2)) * dz;
261 l.unlock();
262 }
263 return fCubicVolume;
264}
G4TemplateAutoLock< G4Mutex > G4AutoLock

◆ GetEntityType()

G4GeometryType G4Paraboloid::GetEntityType ( ) const
overridevirtual

Returns the type ID, "G4Paraboloid" of the solid.

Implements G4VSolid.

Definition at line 945 of file G4Paraboloid.cc.

946{
947 return {"G4Paraboloid"};
948}

◆ GetPointOnSurface()

G4ThreeVector G4Paraboloid::GetPointOnSurface ( ) const
overridevirtual

Returns a random point located and uniformly distributed on the surface of the solid.

Reimplemented from G4VSolid.

Definition at line 984 of file G4Paraboloid.cc.

985{
986 G4double phi = twopi*G4QuickRand();
987 G4double select = fSurfaceArea*G4QuickRand();
988 G4double z, rho;
989 if (select < pi*(sqr(r1) + sqr(r2)))
990 {
991 if(select < pi*sqr(r1))
992 {
993 z = -dz;
994 rho = r1*std::sqrt(G4QuickRand());
995 }
996 else
997 {
998 z = dz;
999 rho = r2*std::sqrt(G4QuickRand());
1000 }
1001 }
1002 else
1003 {
1004 // rejection sampling
1005 G4double mu_max = dz*k1 + k2 + 0.25*k1; // max surface element squared
1006 for (auto i = 0; i < 10000; ++i)
1007 {
1008 z = dz*(2*G4QuickRand() - 1);
1009 G4double mu = z*k1 + k2 + 0.25*k1; // surface element squared
1010 if (mu_max*sqr(G4QuickRand()) <= mu) { break; }
1011 }
1012 rho = std::sqrt(z*k1 + k2);
1013 }
1014 return { rho*std::cos(phi), rho*std::sin(phi), z };
1015}
G4double G4QuickRand(uint32_t seed=0)

◆ GetPolyhedron()

G4Polyhedron * G4Paraboloid::GetPolyhedron ( ) const
overridevirtual

Smart access function - creates on request and stores for future access. A null pointer means "not available".

Reimplemented from G4VSolid.

Definition at line 1031 of file G4Paraboloid.cc.

1032{
1033 if (fpPolyhedron == nullptr ||
1034 fRebuildPolyhedron ||
1035 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1036 fpPolyhedron->GetNumberOfRotationSteps())
1037 {
1038 G4AutoLock l(&polyhedronMutex);
1039 delete fpPolyhedron;
1040 fpPolyhedron = CreatePolyhedron();
1041 fRebuildPolyhedron = false;
1042 l.unlock();
1043 }
1044 return fpPolyhedron;
1045}
G4Polyhedron * CreatePolyhedron() const override

◆ GetRadiusMinusZ()

G4double G4Paraboloid::GetRadiusMinusZ ( ) const
inline

◆ GetRadiusPlusZ()

G4double G4Paraboloid::GetRadiusPlusZ ( ) const
inline

◆ GetSurfaceArea()

G4double G4Paraboloid::GetSurfaceArea ( )
overridevirtual

Returns an estimation of the solid surface area in internal units. This method may be overloaded by derived classes to compute the exact geometrical quantity for solids where this is possible, or anyway to cache the computed value. Note: the computed value is NOT cached.

Reimplemented from G4VSolid.

Definition at line 240 of file G4Paraboloid.cc.

241{
242 if (fSurfaceArea == 0)
243 {
244 G4AutoLock l(&paraboloidMutex);
245 fSurfaceArea = CalculateSurfaceArea();
246 l.unlock();
247 }
248 return fSurfaceArea;
249}

◆ GetZHalfLength()

G4double G4Paraboloid::GetZHalfLength ( ) const
inline

Accessors.

Referenced by G4GDMLWriteSolids::ParaboloidWrite().

◆ Inside()

EInside G4Paraboloid::Inside ( const G4ThreeVector & p) const
overridevirtual

Concrete implementations of the expected query interfaces for solids, as defined in the base class G4VSolid.

Implements G4VSolid.

Definition at line 315 of file G4Paraboloid.cc.

316{
317 // First check is the point is above or below the solid.
318 //
319 if(std::fabs(p.z()) > dz + 0.5 * kCarTolerance) { return kOutside; }
320
321 G4double rho2 = p.perp2(),
322 rhoSurfTimesTol2 = (k1 * p.z() + k2) * sqr(kCarTolerance),
323 A = rho2 - ((k1 *p.z() + k2) + 0.25 * kCarTolerance * kCarTolerance);
324
325 if(A < 0 && sqr(A) > rhoSurfTimesTol2)
326 {
327 // Actually checking rho < radius of paraboloid at z = p.z().
328 // We're either inside or in lower/upper cutoff area.
329
330 if(std::fabs(p.z()) > dz - 0.5 * kCarTolerance)
331 {
332 // We're in the upper/lower cutoff area, sides have a paraboloid shape
333 // maybe further checks should be made to make these nicer
334
335 return kSurface;
336 }
337 return kInside;
338 }
339 if(A <= 0 || sqr(A) < rhoSurfTimesTol2)
340 {
341 // We're in the parabolic surface.
342
343 return kSurface;
344 }
345
346 return kOutside;
347}
@ kSurface
Definition geomdefs.hh:69

Referenced by DistanceToIn(), DistanceToOut(), and DistanceToOut().

◆ operator=()

G4Paraboloid & G4Paraboloid::operator= ( const G4Paraboloid & rhs)

Definition at line 125 of file G4Paraboloid.cc.

126{
127 // Check assignment to self
128 //
129 if (this == &rhs) { return *this; }
130
131 // Copy base class data
132 //
134
135 // Copy data
136 //
137 fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
138 dz = rhs.dz; r1 = rhs.r1; r2 = rhs.r2; k1 = rhs.k1; k2 = rhs.k2;
139 fRebuildPolyhedron = false;
140 delete fpPolyhedron; fpPolyhedron = nullptr;
141
142 return *this;
143}
G4VSolid & operator=(const G4VSolid &rhs)
Definition G4VSolid.cc:108

◆ SetRadiusMinusZ()

void G4Paraboloid::SetRadiusMinusZ ( G4double R1)

Definition at line 193 of file G4Paraboloid.cc.

194{
195 if(pR1 < 0 || pR1 >= r2)
196 {
197 G4Exception("G4Paraboloid::SetRadiusMinusZ()", "GeomSolids0002",
198 FatalException, "Invalid dimensions.");
199 }
200 else
201 {
202 r1 = pR1;
203 k1 = (sqr(r2) - sqr(r1)) / (2 * dz);
204 k2 = (sqr(r2) + sqr(r1)) / 2;
205 fSurfaceArea = CalculateSurfaceArea();
206 fCubicVolume = 0.;
207 fRebuildPolyhedron = true;
208 }
209}
@ FatalException

◆ SetRadiusPlusZ()

void G4Paraboloid::SetRadiusPlusZ ( G4double R2)

Definition at line 171 of file G4Paraboloid.cc.

172{
173 if(pR2 <= 0 || pR2 <= r1)
174 {
175 G4Exception("G4Paraboloid::SetRadiusPlusZ()", "GeomSolids0002",
176 FatalException, "Invalid dimensions.");
177 }
178 else
179 {
180 r2 = pR2;
181 k1 = (sqr(r2) - sqr(r1)) / (2 * dz);
182 k2 = (sqr(r2) + sqr(r1)) / 2;
183 fSurfaceArea = CalculateSurfaceArea();
184 fCubicVolume = 0.;
185 fRebuildPolyhedron = true;
186 }
187}

◆ SetZHalfLength()

void G4Paraboloid::SetZHalfLength ( G4double dz)

Modifiers.

Definition at line 149 of file G4Paraboloid.cc.

150{
151 if(pDz <= 0)
152 {
153 G4Exception("G4Paraboloid::SetZHalfLength()", "GeomSolids0002",
154 FatalException, "Invalid dimensions.");
155 }
156 else
157 {
158 dz = pDz;
159 k1 = (sqr(r2) - sqr(r1)) / (2 * dz);
160 k2 = (sqr(r2) + sqr(r1)) / 2;
161 fSurfaceArea = CalculateSurfaceArea();
162 fCubicVolume = 0.;
163 fRebuildPolyhedron = true;
164 }
165}

◆ StreamInfo()

std::ostream & G4Paraboloid::StreamInfo ( std::ostream & os) const
overridevirtual

Streams the object contents to an output stream.

Implements G4VSolid.

Definition at line 963 of file G4Paraboloid.cc.

964{
965 G4long oldprc = os.precision(16);
966 os << "-----------------------------------------------------------\n"
967 << " *** Dump for solid - " << GetName() << " ***\n"
968 << " ===================================================\n"
969 << " Solid type: G4Paraboloid\n"
970 << " Parameters: \n"
971 << " z half-axis: " << dz/mm << " mm \n"
972 << " radius at -dz: " << r1/mm << " mm \n"
973 << " radius at dz: " << r2/mm << " mm \n"
974 << "-----------------------------------------------------------\n";
975 os.precision(oldprc);
976
977 return os;
978}

◆ SurfaceNormal()

G4ThreeVector G4Paraboloid::SurfaceNormal ( const G4ThreeVector & p) const
overridevirtual

Returns the outwards pointing unit normal of the shape for the surface closest to the point at offset 'p'.

Parameters
[in]pThe point at offset p.
Returns
The outwards pointing unit normal.

Implements G4VSolid.

Definition at line 353 of file G4Paraboloid.cc.

354{
355 G4ThreeVector n(0, 0, 0);
356 if(std::fabs(p.z()) > dz + 0.5 * kCarTolerance)
357 {
358 // If above or below just return normal vector for the cutoff plane.
359
360 n = G4ThreeVector(0, 0, p.z()/std::fabs(p.z()));
361 }
362 else if(std::fabs(p.z()) > dz - 0.5 * kCarTolerance)
363 {
364 // This means we're somewhere in the plane z = dz or z = -dz.
365 // (As far as the program is concerned anyway.
366
367 if(p.z() < 0) // Are we in upper or lower plane?
368 {
369 if(p.perp2() > sqr(r1 + 0.5 * kCarTolerance))
370 {
371 n = G4ThreeVector(p.x(), p.y(), -k1 / 2).unit();
372 }
373 else if(r1 < 0.5 * kCarTolerance
374 || p.perp2() > sqr(r1 - 0.5 * kCarTolerance))
375 {
376 n = G4ThreeVector(p.x(), p.y(), 0.).unit()
377 + G4ThreeVector(0., 0., -1.).unit();
378 n = n.unit();
379 }
380 else
381 {
382 n = G4ThreeVector(0., 0., -1.);
383 }
384 }
385 else
386 {
387 if(p.perp2() > sqr(r2 + 0.5 * kCarTolerance))
388 {
389 n = G4ThreeVector(p.x(), p.y(), 0.).unit();
390 }
391 else if(r2 < 0.5 * kCarTolerance
392 || p.perp2() > sqr(r2 - 0.5 * kCarTolerance))
393 {
394 n = G4ThreeVector(p.x(), p.y(), 0.).unit()
395 + G4ThreeVector(0., 0., 1.).unit();
396 n = n.unit();
397 }
398 else
399 {
400 n = G4ThreeVector(0., 0., 1.);
401 }
402 }
403 }
404 else
405 {
406 G4double rho2 = p.perp2();
407 G4double rhoSurfTimesTol2 = (k1 * p.z() + k2) * sqr(kCarTolerance);
408 G4double A = rho2 - ((k1 *p.z() + k2)
409 + 0.25 * kCarTolerance * kCarTolerance);
410
411 if(A < 0 && sqr(A) > rhoSurfTimesTol2)
412 {
413 // Actually checking rho < radius of paraboloid at z = p.z().
414 // We're inside.
415
416 if(p.mag2() != 0) { n = p.unit(); }
417 }
418 else if(A <= 0 || sqr(A) < rhoSurfTimesTol2)
419 {
420 // We're in the parabolic surface.
421
422 n = G4ThreeVector(p.x(), p.y(), - k1 / 2).unit();
423 }
424 else
425 {
426 n = G4ThreeVector(p.x(), p.y(), - k1 / 2).unit();
427 }
428 }
429
430 if(n.mag2() == 0)
431 {
432 std::ostringstream message;
433 message << "No normal defined for this point p." << G4endl
434 << " p = " << 1 / mm * p << " mm";
435 G4Exception("G4Paraboloid::SurfaceNormal(p)", "GeomSolids1002",
436 JustWarning, message);
437 }
438 return n;
439}
double mag2() const

The documentation for this class was generated from the following files: