Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:14:15

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   /// Getter for the structure storing hyperboloid data.
0065   VECCORE_ATT_HOST_DEVICE
0066   HypeStruct<Precision> const &GetStruct() const { return fHype; }
0067 
0068   /// Getter for tolerance relative to the Z half-length.
0069   VECCORE_ATT_HOST_DEVICE
0070   VECGEOM_FORCE_INLINE
0071   Precision GetZToleranceLevel() const { return fHype.zToleranceLevel; }
0072 
0073   /// Getter for tolerance relative to the inner radius.
0074   VECCORE_ATT_HOST_DEVICE
0075   VECGEOM_FORCE_INLINE
0076   Precision GetInnerRadToleranceLevel() const { return fHype.innerRadToleranceLevel; }
0077 
0078   /// Getter for tolerance relative to the outer radius.
0079   VECCORE_ATT_HOST_DEVICE
0080   VECGEOM_FORCE_INLINE
0081   Precision GetOuterRadToleranceLevel() const { return fHype.outerRadToleranceLevel; }
0082 
0083   /// Getter for the inner radius.
0084   VECCORE_ATT_HOST_DEVICE
0085   VECGEOM_FORCE_INLINE
0086   Precision GetRmin() const { return fHype.fRmin; }
0087 
0088   /// Getter for the outer radius.
0089   VECCORE_ATT_HOST_DEVICE
0090   VECGEOM_FORCE_INLINE
0091   Precision GetRmax() const { return fHype.fRmax; }
0092 
0093   /// Getter for the squared inner radius.
0094   VECCORE_ATT_HOST_DEVICE
0095   VECGEOM_FORCE_INLINE
0096   Precision GetRmin2() const { return fHype.fRmin2; }
0097 
0098   /// Getter for the squared outer radius.
0099   VECCORE_ATT_HOST_DEVICE
0100   VECGEOM_FORCE_INLINE
0101   Precision GetRmax2() const { return fHype.fRmax2; }
0102 
0103   /// Getter for the inner angle of the inner surface.
0104   VECCORE_ATT_HOST_DEVICE
0105   VECGEOM_FORCE_INLINE
0106   Precision GetStIn() const { return fHype.fStIn; }
0107 
0108   /// Getter for the inner angle of the outer surface.
0109   VECCORE_ATT_HOST_DEVICE
0110   VECGEOM_FORCE_INLINE
0111   Precision GetStOut() const { return fHype.fStOut; }
0112 
0113   /// Getter for the tangent of the inner stereo angle.
0114   VECCORE_ATT_HOST_DEVICE
0115   VECGEOM_FORCE_INLINE
0116   Precision GetTIn() const { return fHype.fTIn; }
0117 
0118   /// Getter for the tangent of the outer stereo angle.
0119   VECCORE_ATT_HOST_DEVICE
0120   VECGEOM_FORCE_INLINE
0121   Precision GetTOut() const { return fHype.fTOut; }
0122 
0123   /// Getter for the squared tangent of the inner stereo angle.
0124   VECCORE_ATT_HOST_DEVICE
0125   VECGEOM_FORCE_INLINE
0126   Precision GetTIn2() const { return fHype.fTIn2; }
0127 
0128   /// Getter for the squared tangent of the outer stereo angle.
0129   VECCORE_ATT_HOST_DEVICE
0130   VECGEOM_FORCE_INLINE
0131   Precision GetTOut2() const { return fHype.fTOut2; }
0132 
0133   /// Getter for the inverse of the tangent of the inner stereo angle.
0134   VECCORE_ATT_HOST_DEVICE
0135   VECGEOM_FORCE_INLINE
0136   Precision GetTIn2Inv() const { return fHype.fTIn2Inv; }
0137 
0138   /// Getter for the inverse of the tangent of the outer stereo angle.
0139   VECCORE_ATT_HOST_DEVICE
0140   VECGEOM_FORCE_INLINE
0141   Precision GetTOut2Inv() const { return fHype.fTOut2Inv; }
0142 
0143   /// Getter for the half-length in Z.
0144   VECCORE_ATT_HOST_DEVICE
0145   VECGEOM_FORCE_INLINE
0146   Precision GetDz() const { return fHype.fDz; }
0147 
0148   /// Getter for the squared half-length in Z.
0149   VECCORE_ATT_HOST_DEVICE
0150   VECGEOM_FORCE_INLINE
0151   Precision GetDz2() const { return fHype.fDz2; }
0152 
0153   /// Getter for the inner radius of endcaps.
0154   VECCORE_ATT_HOST_DEVICE
0155   VECGEOM_FORCE_INLINE
0156   Precision GetEndInnerRadius() const { return fHype.fEndInnerRadius; }
0157 
0158   /// Getter for the squared inner radius of endcaps.
0159   VECCORE_ATT_HOST_DEVICE
0160   VECGEOM_FORCE_INLINE
0161   Precision GetEndInnerRadius2() const { return fHype.fEndInnerRadius2; }
0162 
0163   /// Getter for the outer radius of endcaps.
0164   VECCORE_ATT_HOST_DEVICE
0165   VECGEOM_FORCE_INLINE
0166   Precision GetEndOuterRadius() const { return fHype.fEndOuterRadius; }
0167 
0168   /// Getter for the squared outer radius of endcaps.
0169   VECCORE_ATT_HOST_DEVICE
0170   VECGEOM_FORCE_INLINE
0171   Precision GetEndOuterRadius2() const { return fHype.fEndOuterRadius2; }
0172 
0173   /// Getter for the side of the square inscribed in the inner circle.
0174   VECCORE_ATT_HOST_DEVICE
0175   VECGEOM_FORCE_INLINE
0176   Precision GetInSqSide() const { return fHype.fInSqSide; }
0177 
0178   /// Method to set the parameters of the hyperboloid, used by the constructor.
0179   /** @param rMin  Inner radius.
0180       @param rMax  Outer radius.
0181       @param stIn  Stereo angle for inner surface.
0182       @param stOut Stereo angle for outer surface.
0183       @param dz    Half length in Z.
0184   */
0185   VECCORE_ATT_HOST_DEVICE
0186   VECGEOM_FORCE_INLINE
0187   void SetParameters(const Precision rMin, const Precision rMax, const Precision stIn, const Precision stOut,
0188                      const Precision dz)
0189   {
0190     fHype.SetParameters(rMin, rMax, stIn, stOut, dz);
0191     DetectConvexity();
0192   }
0193 
0194   /// Method to compute the volume of the inner/outer hyperboloids.
0195   /** @param  outer Flag if it is about outer surface or inner one.
0196       @return The value of the volume for the inner/outer hype.
0197   */
0198   VECCORE_ATT_HOST_DEVICE
0199   Precision Volume(bool outer);
0200 
0201   /// Method to compute the surface area of the inner/outer hyperboloids.
0202   /** @param  outer Flag if it is about outer surface or inner one.
0203       @return The value of the area for the inner/outer hype.
0204   */
0205   VECCORE_ATT_HOST_DEVICE
0206   Precision Area(bool outer);
0207 
0208   /// Method to compute the area of hyperboloid endcaps.
0209   /** @return The value of the area for endcaps.*/
0210   VECCORE_ATT_HOST_DEVICE
0211   Precision AreaEndCaps();
0212 
0213   /// Method to compute and cache the capacity of the hyperboloid.
0214   VECCORE_ATT_HOST_DEVICE
0215   void CalcCapacity();
0216 
0217   /// Method to compute and cache the surface area of the hyperboloid.
0218   VECCORE_ATT_HOST_DEVICE
0219   void CalcSurfaceArea();
0220 
0221   /// Method to detect and cache the convexity of the hyperboloid.
0222   VECCORE_ATT_HOST_DEVICE
0223   void DetectConvexity();
0224 
0225   VECCORE_ATT_HOST_DEVICE
0226   void Extent(Vector3D<Precision> &, Vector3D<Precision> &) const override;
0227 
0228   Precision Capacity() const override { return fHype.fCubicVolume; }
0229 
0230   // VECCORE_ATT_HOST_DEVICE
0231   Precision SurfaceArea() const override { return fHype.fSurfaceArea; }
0232 
0233   /// Method to determine the squared hyperboloid radius at a given Z, for either the inner or the outer surfaces
0234   /// (template parameter).
0235   /** @param  dz Value of the Z coordinate.
0236       @return Squared radius of the hyperboloid surface.
0237   */
0238   template <bool ForInnerSurface>
0239   VECGEOM_FORCE_INLINE
0240   VECCORE_ATT_HOST_DEVICE
0241   Precision GetHypeRadius2(Precision dz) const
0242   {
0243     if (ForInnerSurface)
0244       return GetRmin2() + GetTIn2() * dz * dz;
0245     else
0246       return GetRmax2() + GetTOut2() * dz * dz;
0247   }
0248 
0249   /// Method to check if a point has a Z coordinate compatible with one of the Z surfaces.
0250   /** @param  p Point for which the check is made.
0251       @return True if point is within Z tolerance.
0252   */
0253   VECCORE_ATT_HOST_DEVICE
0254   VECGEOM_FORCE_INLINE
0255   bool PointOnZSurface(Vector3D<Precision> const &p) const
0256   {
0257     return (p.z() > (GetDz() - GetZToleranceLevel())) && (p.z() < (GetDz() + GetZToleranceLevel()));
0258   }
0259 
0260   /// Method to check if a point is on the inner/outer hype surface (template parameter).
0261   /** @param  p Point for which the check is made.
0262       @return True if point is on the hype surface within the outer radius tolerance.
0263   */
0264   template <bool ForInnerSurface>
0265   VECGEOM_FORCE_INLINE
0266   VECCORE_ATT_HOST_DEVICE
0267   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 SIMDUnplacedVolumeImplHelper<HypeImplementation<HypeType>, UnplacedHype>,
0369                       public AlignedBase {
0370 public:
0371   using BaseType_t = SIMDUnplacedVolumeImplHelper<HypeImplementation<HypeType>, UnplacedHype>;
0372   using BaseType_t::BaseType_t;
0373 
0374   template <TranslationCode transCodeT, RotationCode rotCodeT>
0375   VECCORE_ATT_DEVICE
0376   static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
0377 #ifdef VECCORE_CUDA
0378                                const int id, const int copy_no, const int child_id,
0379 #endif
0380                                VPlacedVolume *const placement = NULL);
0381 
0382 private:
0383 #ifndef VECCORE_CUDA
0384   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0385                                            Transformation3D const *const transformation,
0386                                            const TranslationCode trans_code, const RotationCode rot_code,
0387                                            VPlacedVolume *const placement = NULL) const override
0388   {
0389     return VolumeFactory::CreateByTransformation<SUnplacedHype<HypeType>>(volume, transformation, trans_code, rot_code,
0390                                                                           placement);
0391   }
0392 
0393 #else
0394   VECCORE_ATT_DEVICE
0395   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0396                                            Transformation3D const *const transformation,
0397                                            const TranslationCode trans_code, const RotationCode rot_code, const int id,
0398                                            const int copy_no, const int child_id,
0399                                            VPlacedVolume *const placement = NULL) const override
0400   {
0401     return VolumeFactory::CreateByTransformation<SUnplacedHype<HypeType>>(volume, transformation, trans_code, rot_code,
0402                                                                           id, copy_no, child_id, placement);
0403   }
0404 #endif
0405 };
0406 
0407 using GenericUnplacedHype = SUnplacedHype<HypeTypes::UniversalHype>;
0408 
0409 } // namespace VECGEOM_IMPL_NAMESPACE
0410 } // namespace vecgeom
0411 
0412 #include "VecGeom/volumes/SpecializedHype.h"
0413 
0414 #endif // VECGEOM_VOLUMES_UNPLACEDHYPE_H_