Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-18 09:33:09

0001 // This file is part of VecGeom and is distributed under the
0002 // conditions in the file LICENSE.txt in the top directory.
0003 // For the full list of authors see CONTRIBUTORS.txt and `git log`.
0004 
0005 /// \brief Declaration of the unplaced hyperboloid shape
0006 /// \file volumes/UnplacedHype.h
0007 /// \author First version created by Marilena Bandieramonte (CERN).
0008 
0009 #ifndef VECGEOM_VOLUMES_UNPLACEDHYPE_H_
0010 #define VECGEOM_VOLUMES_UNPLACEDHYPE_H_
0011 
0012 #include "VecGeom/base/Cuda.h"
0013 #include "VecGeom/base/Global.h"
0014 #include "VecGeom/base/AlignedBase.h"
0015 #include "VecGeom/volumes/UnplacedVolume.h"
0016 #include "VecGeom/volumes/HypeStruct.h"
0017 #include "VecGeom/volumes/kernel/HypeImplementation.h"
0018 #include "VecGeom/volumes/UnplacedVolumeImplHelper.h"
0019 
0020 namespace vecgeom {
0021 
0022 VECGEOM_DEVICE_FORWARD_DECLARE(class UnplacedHype;);
0023 VECGEOM_DEVICE_DECLARE_CONV(class, UnplacedHype);
0024 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE(class, SUnplacedHype, typename);
0025 
0026 inline namespace VECGEOM_IMPL_NAMESPACE {
0027 
0028 /** Class for hyperboloid shape primitive.
0029 
0030   Hyperboloid class is defined by 5 parameters
0031   A Hype is the solid bounded by the following surfaces:
0032   - 2 planes parallel with XY cutting the Z axis at Z=-dz and Z=+dz
0033   - Inner and outer lateral surfaces. These represent the surfaces
0034   described by the revolution of 2 hyperbolas about the Z axis:
0035   r^2 - (t*z)^2 = a^2 where:
0036   r = distance between hyperbola and Z axis at coordinate z
0037   t = tangent of the stereo angle (angle made by hyperbola asimptotic lines and Z axis). t=0 means cylindrical
0038   surface.
0039   a = distance between hyperbola and Z axis at z=0
0040 */
0041 class UnplacedHype : public VUnplacedVolume {
0042 
0043 private:
0044   HypeStruct<Precision> fHype; ///< Structure holding the data for Hype
0045 
0046 public:
0047   /// Default constructor for the unplaced hyperboloid.
0048   /** The constructor takes 5 parameters: inner and outer radius, stereo angles and half length in Z.
0049       @param rMin  Inner radius.
0050       @param rMax  Outer radius.
0051       @param stIn  Stereo angle for inner surface.
0052       @param stOut Stereo angle for outer surface.
0053       @param dz    Half length in Z.
0054   */
0055   VECCORE_ATT_HOST_DEVICE
0056   UnplacedHype(const Precision rMin, const Precision rMax, const Precision stIn, const Precision stOut,
0057                const Precision dz)
0058       : fHype(rMin, rMax, stIn, stOut, dz)
0059   {
0060     DetectConvexity();
0061     ComputeBBox();
0062   }
0063 
0064   VECCORE_ATT_HOST_DEVICE
0065   VECGEOM_FORCE_INLINE
0066   virtual ESolidType GetType() const override { return ESolidType::hyperboloid; }
0067 
0068   /// Getter for the structure storing hyperboloid data.
0069   VECCORE_ATT_HOST_DEVICE
0070   HypeStruct<Precision> const &GetStruct() const { return fHype; }
0071 
0072   /// Getter for tolerance relative to the Z half-length.
0073   VECCORE_ATT_HOST_DEVICE
0074   VECGEOM_FORCE_INLINE
0075   Precision GetZToleranceLevel() const { return fHype.zToleranceLevel; }
0076 
0077   /// Getter for tolerance relative to the inner radius.
0078   VECCORE_ATT_HOST_DEVICE
0079   VECGEOM_FORCE_INLINE
0080   Precision GetInnerRadToleranceLevel() const { return fHype.innerRadToleranceLevel; }
0081 
0082   /// Getter for tolerance relative to the outer radius.
0083   VECCORE_ATT_HOST_DEVICE
0084   VECGEOM_FORCE_INLINE
0085   Precision GetOuterRadToleranceLevel() const { return fHype.outerRadToleranceLevel; }
0086 
0087   /// Getter for the inner radius.
0088   VECCORE_ATT_HOST_DEVICE
0089   VECGEOM_FORCE_INLINE
0090   Precision GetRmin() const { return fHype.fRmin; }
0091 
0092   /// Getter for the outer radius.
0093   VECCORE_ATT_HOST_DEVICE
0094   VECGEOM_FORCE_INLINE
0095   Precision GetRmax() const { return fHype.fRmax; }
0096 
0097   /// Getter for the squared inner radius.
0098   VECCORE_ATT_HOST_DEVICE
0099   VECGEOM_FORCE_INLINE
0100   Precision GetRmin2() const { return fHype.fRmin2; }
0101 
0102   /// Getter for the squared outer radius.
0103   VECCORE_ATT_HOST_DEVICE
0104   VECGEOM_FORCE_INLINE
0105   Precision GetRmax2() const { return fHype.fRmax2; }
0106 
0107   /// Getter for the inner angle of the inner surface.
0108   VECCORE_ATT_HOST_DEVICE
0109   VECGEOM_FORCE_INLINE
0110   Precision GetStIn() const { return fHype.fStIn; }
0111 
0112   /// Getter for the inner angle of the outer surface.
0113   VECCORE_ATT_HOST_DEVICE
0114   VECGEOM_FORCE_INLINE
0115   Precision GetStOut() const { return fHype.fStOut; }
0116 
0117   /// Getter for the tangent of the inner stereo angle.
0118   VECCORE_ATT_HOST_DEVICE
0119   VECGEOM_FORCE_INLINE
0120   Precision GetTIn() const { return fHype.fTIn; }
0121 
0122   /// Getter for the tangent of the outer stereo angle.
0123   VECCORE_ATT_HOST_DEVICE
0124   VECGEOM_FORCE_INLINE
0125   Precision GetTOut() const { return fHype.fTOut; }
0126 
0127   /// Getter for the squared tangent of the inner stereo angle.
0128   VECCORE_ATT_HOST_DEVICE
0129   VECGEOM_FORCE_INLINE
0130   Precision GetTIn2() const { return fHype.fTIn2; }
0131 
0132   /// Getter for the squared tangent of the outer stereo angle.
0133   VECCORE_ATT_HOST_DEVICE
0134   VECGEOM_FORCE_INLINE
0135   Precision GetTOut2() const { return fHype.fTOut2; }
0136 
0137   /// Getter for the inverse of the tangent of the inner stereo angle.
0138   VECCORE_ATT_HOST_DEVICE
0139   VECGEOM_FORCE_INLINE
0140   Precision GetTIn2Inv() const { return fHype.fTIn2Inv; }
0141 
0142   /// Getter for the inverse of the tangent of the outer stereo angle.
0143   VECCORE_ATT_HOST_DEVICE
0144   VECGEOM_FORCE_INLINE
0145   Precision GetTOut2Inv() const { return fHype.fTOut2Inv; }
0146 
0147   /// Getter for the half-length in Z.
0148   VECCORE_ATT_HOST_DEVICE
0149   VECGEOM_FORCE_INLINE
0150   Precision GetDz() const { return fHype.fDz; }
0151 
0152   /// Getter for the squared half-length in Z.
0153   VECCORE_ATT_HOST_DEVICE
0154   VECGEOM_FORCE_INLINE
0155   Precision GetDz2() const { return fHype.fDz2; }
0156 
0157   /// Getter for the inner radius of endcaps.
0158   VECCORE_ATT_HOST_DEVICE
0159   VECGEOM_FORCE_INLINE
0160   Precision GetEndInnerRadius() const { return fHype.fEndInnerRadius; }
0161 
0162   /// Getter for the squared inner radius of endcaps.
0163   VECCORE_ATT_HOST_DEVICE
0164   VECGEOM_FORCE_INLINE
0165   Precision GetEndInnerRadius2() const { return fHype.fEndInnerRadius2; }
0166 
0167   /// Getter for the outer radius of endcaps.
0168   VECCORE_ATT_HOST_DEVICE
0169   VECGEOM_FORCE_INLINE
0170   Precision GetEndOuterRadius() const { return fHype.fEndOuterRadius; }
0171 
0172   /// Getter for the squared outer radius of endcaps.
0173   VECCORE_ATT_HOST_DEVICE
0174   VECGEOM_FORCE_INLINE
0175   Precision GetEndOuterRadius2() const { return fHype.fEndOuterRadius2; }
0176 
0177   /// Getter for the side of the square inscribed in the inner circle.
0178   VECCORE_ATT_HOST_DEVICE
0179   VECGEOM_FORCE_INLINE
0180   Precision GetInSqSide() const { return fHype.fInSqSide; }
0181 
0182   /// Method to set the parameters of the hyperboloid, used by the constructor.
0183   /** @param rMin  Inner radius.
0184       @param rMax  Outer radius.
0185       @param stIn  Stereo angle for inner surface.
0186       @param stOut Stereo angle for outer surface.
0187       @param dz    Half length in Z.
0188   */
0189   VECCORE_ATT_HOST_DEVICE
0190   VECGEOM_FORCE_INLINE
0191   void SetParameters(const Precision rMin, const Precision rMax, const Precision stIn, const Precision stOut,
0192                      const Precision dz)
0193   {
0194     fHype.SetParameters(rMin, rMax, stIn, stOut, dz);
0195     DetectConvexity();
0196   }
0197 
0198   /// Method to compute the volume of the inner/outer hyperboloids.
0199   /** @param  outer Flag if it is about outer surface or inner one.
0200       @return The value of the volume for the inner/outer hype.
0201   */
0202   VECCORE_ATT_HOST_DEVICE
0203   Precision Volume(bool outer);
0204 
0205   /// Method to compute the surface area of the inner/outer hyperboloids.
0206   /** @param  outer Flag if it is about outer surface or inner one.
0207       @return The value of the area for the inner/outer hype.
0208   */
0209   VECCORE_ATT_HOST_DEVICE
0210   Precision Area(bool outer);
0211 
0212   /// Method to compute the area of hyperboloid endcaps.
0213   /** @return The value of the area for endcaps.*/
0214   VECCORE_ATT_HOST_DEVICE
0215   Precision AreaEndCaps();
0216 
0217   /// Method to compute and cache the capacity of the hyperboloid.
0218   VECCORE_ATT_HOST_DEVICE
0219   void CalcCapacity();
0220 
0221   /// Method to compute and cache the surface area of the hyperboloid.
0222   VECCORE_ATT_HOST_DEVICE
0223   void CalcSurfaceArea();
0224 
0225   /// Method to detect and cache the convexity of the hyperboloid.
0226   VECCORE_ATT_HOST_DEVICE
0227   void DetectConvexity();
0228 
0229   VECCORE_ATT_HOST_DEVICE
0230   void Extent(Vector3D<Precision> &, Vector3D<Precision> &) const override;
0231 
0232   Precision Capacity() const override { return fHype.fCubicVolume; }
0233 
0234   // VECCORE_ATT_HOST_DEVICE
0235   Precision SurfaceArea() const override { return fHype.fSurfaceArea; }
0236 
0237   /// Method to determine the squared hyperboloid radius at a given Z, for either the inner or the outer surfaces
0238   /// (template parameter).
0239   /** @param  dz Value of the Z coordinate.
0240       @return Squared radius of the hyperboloid surface.
0241   */
0242   template <bool ForInnerSurface>
0243   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Precision GetHypeRadius2(Precision dz) const
0244   {
0245     if (ForInnerSurface)
0246       return GetRmin2() + GetTIn2() * dz * dz;
0247     else
0248       return GetRmax2() + GetTOut2() * dz * dz;
0249   }
0250 
0251   /// Method to check if a point has a Z coordinate compatible with one of the Z surfaces.
0252   /** @param  p Point for which the check is made.
0253       @return True if point is within Z tolerance.
0254   */
0255   VECCORE_ATT_HOST_DEVICE
0256   VECGEOM_FORCE_INLINE
0257   bool PointOnZSurface(Vector3D<Precision> const &p) const
0258   {
0259     return (p.z() > (GetDz() - GetZToleranceLevel())) && (p.z() < (GetDz() + GetZToleranceLevel()));
0260   }
0261 
0262   /// Method to check if a point is on the inner/outer hype surface (template parameter).
0263   /** @param  p Point for which the check is made.
0264       @return True if point is on the hype surface within the outer radius tolerance.
0265   */
0266   template <bool ForInnerSurface>
0267   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE bool PointOnHyperbolicSurface(Vector3D<Precision> const &p) const
0268   {
0269     Precision hypeR2    = 0.;
0270     hypeR2              = GetHypeRadius2<ForInnerSurface>(p.z());
0271     Precision pointRad2 = p.Perp2();
0272     return ((pointRad2 > (hypeR2 - GetOuterRadToleranceLevel())) &&
0273             (pointRad2 < (hypeR2 + GetOuterRadToleranceLevel())));
0274   }
0275 
0276   VECCORE_ATT_HOST_DEVICE
0277   bool Normal(Vector3D<Precision> const &p, Vector3D<Precision> &normal) const override
0278   {
0279 
0280     bool valid = true;
0281 
0282     Precision absZ(std::fabs(p.z()));
0283     Precision distZ(absZ - GetDz());
0284     Precision dist2Z(distZ * distZ);
0285 
0286     Precision xR2 = p.Perp2();
0287     Precision dist2Outer(std::fabs(xR2 - GetHypeRadius2<false>(absZ)));
0288     Precision dist2Inner(std::fabs(xR2 - GetHypeRadius2<true>(absZ)));
0289 
0290     // EndCap
0291     if (PointOnZSurface(p) || ((dist2Z < dist2Inner) && (dist2Z < dist2Outer)))
0292       normal = Vector3D<Precision>(0.0, 0.0, p.z() < 0 ? -1.0 : 1.0);
0293 
0294     // OuterHyperbolic Surface
0295     if (PointOnHyperbolicSurface<false>(p) || ((dist2Outer < dist2Inner) && (dist2Outer < dist2Z)))
0296       normal = Vector3D<Precision>(p.x(), p.y(), -p.z() * GetTOut2()).Unit();
0297 
0298     // InnerHyperbolic Surface
0299     if (PointOnHyperbolicSurface<true>(p) || ((dist2Inner < dist2Outer) && (dist2Inner < dist2Z)))
0300       normal = Vector3D<Precision>(-p.x(), -p.y(), p.z() * GetTIn2()).Unit();
0301 
0302     return valid;
0303   }
0304 
0305   Vector3D<Precision> SamplePointOnSurface() const override;
0306 
0307   /// Get the solid type as string.
0308   /** @return Name of the solid type.*/
0309   std::string GetEntityType() const;
0310 
0311   /// Get list of hyperboloid parameters as an array.
0312   /** @param[in]  aNumber Not used.
0313       @param[out] aArray User array to be filled (rMin, stIn, rMax, stOut, dz)
0314   */
0315   VECCORE_ATT_HOST_DEVICE
0316   void GetParametersList(int aNumber, Precision *aArray) const;
0317 
0318   VECCORE_ATT_HOST_DEVICE
0319   UnplacedHype *Clone() const;
0320 
0321   std::ostream &StreamInfo(std::ostream &os) const;
0322 
0323   /// Method to determine of the inner surface exists.
0324   /** @return True if the inner radius is zero. */
0325   VECCORE_ATT_HOST_DEVICE
0326   bool InnerSurfaceExists() const;
0327 
0328   virtual int MemorySize() const override { return sizeof(*this); }
0329 
0330   VECCORE_ATT_HOST_DEVICE
0331   virtual void Print() const override;
0332 
0333   virtual void Print(std::ostream &os) const override;
0334 
0335 #ifndef VECCORE_CUDA
0336   virtual SolidMesh *CreateMesh3D(Transformation3D const &trans, size_t nSegments) const override;
0337 #endif
0338 
0339 #ifdef VECGEOM_CUDA_INTERFACE
0340   virtual size_t DeviceSizeOf() const override
0341   {
0342     return DevicePtr<cuda::SUnplacedHype<cuda::HypeTypes::UniversalHype>>::SizeOf();
0343   }
0344   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const override;
0345   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const override;
0346 #endif
0347 
0348 #ifndef VECCORE_CUDA
0349 #ifdef VECGEOM_ROOT
0350   TGeoShape const *ConvertToRoot(char const *label) const;
0351 #endif
0352 
0353 #ifdef VECGEOM_GEANT4
0354   G4VSolid const *ConvertToGeant4(char const *label) const;
0355 #endif
0356 #endif
0357 };
0358 
0359 template <>
0360 struct Maker<UnplacedHype> {
0361   template <typename... ArgTypes>
0362   static UnplacedHype *MakeInstance(const Precision rMin, const Precision rMax, const Precision stIn,
0363                                     const Precision stOut, const Precision dz);
0364 };
0365 
0366 /** Specialized version of the unplaced hyperboloid, supporting universal/hollow/non-hollow types.*/
0367 template <typename HypeType = HypeTypes::UniversalHype>
0368 class SUnplacedHype : public UnplacedVolumeImplHelper<HypeImplementation<HypeType>, UnplacedHype>, public AlignedBase {
0369 public:
0370   using BaseType_t = UnplacedVolumeImplHelper<HypeImplementation<HypeType>, UnplacedHype>;
0371   using BaseType_t::BaseType_t;
0372 
0373   VECCORE_ATT_DEVICE
0374   static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
0375 #ifdef VECCORE_CUDA
0376                                const int id, const int copy_no, const int child_id,
0377 #endif
0378                                VPlacedVolume *const placement = NULL);
0379 
0380 private:
0381 #ifndef VECCORE_CUDA
0382   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0383                                            Transformation3D const *const transformation,
0384                                            VPlacedVolume *const placement = NULL) const override
0385   {
0386     return VolumeFactory::CreateByTransformation<SUnplacedHype<HypeType>>(volume, transformation, placement);
0387   }
0388 
0389 #else
0390   VECCORE_ATT_DEVICE
0391   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0392                                            Transformation3D const *const transformation, const int id,
0393                                            const int copy_no, const int child_id,
0394                                            VPlacedVolume *const placement = NULL) const override
0395   {
0396     return VolumeFactory::CreateByTransformation<SUnplacedHype<HypeType>>(volume, transformation, id, copy_no, child_id,
0397                                                                           placement);
0398   }
0399 #endif
0400 };
0401 
0402 using GenericUnplacedHype = SUnplacedHype<HypeTypes::UniversalHype>;
0403 
0404 } // namespace VECGEOM_IMPL_NAMESPACE
0405 } // namespace vecgeom
0406 
0407 #include "VecGeom/volumes/SpecializedHype.h"
0408 
0409 #endif // VECGEOM_VOLUMES_UNPLACEDHYPE_H_