Back to home page

EIC code displayed by LXR

 
 

    


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

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 volume interfaces.
0006 /// \file volumes/UnplacedVolume.h
0007 /// \author created by Sandro Wenzel
0008 
0009 #ifndef VECGEOM_VOLUMES_UNPLACEDVOLUME_H_
0010 #define VECGEOM_VOLUMES_UNPLACEDVOLUME_H_
0011 
0012 #include "VecGeom/base/Cuda.h"
0013 #include "VecGeom/base/Global.h"
0014 #include "VecGeom/base/Transformation3D.h"
0015 #include "VecGeom/base/SOA3D.h"
0016 #include "VecGeom/volumes/kernel/BoxImplementation.h"
0017 #include <string>
0018 #include <ostream>
0019 
0020 #ifndef VECCORE_CUDA
0021 #include "VecGeom/volumes/SolidMesh.h"
0022 #endif
0023 
0024 namespace vecgeom {
0025 
0026 VECGEOM_DEVICE_FORWARD_DECLARE(class VUnplacedVolume;);
0027 VECGEOM_DEVICE_DECLARE_CONV(class, VUnplacedVolume);
0028 
0029 inline namespace VECGEOM_IMPL_NAMESPACE {
0030 
0031 class LogicalVolume;
0032 class VPlacedVolume;
0033 
0034 /**
0035  * The abstract interface class for unplaced volumes.
0036  *
0037  * An unplaced volume represents a geometry shape (primitive) and offers
0038  * interfaces to query distance, location, containment, etc. in its "natural"
0039  * system of coordinates.
0040  */
0041 class VUnplacedVolume {
0042 
0043 private:
0044   friend class CudaManager;
0045   Vector3D<Precision> fBBox[2]; ///< bounding box corners
0046 
0047 protected:
0048   bool fGlobalConvexity;
0049   bool fIsAssembly = false; // indicates if this volume is an assembly
0050 
0051 public:
0052   // alias for the globally selected VectorType
0053   using Real_v = vecgeom::VectorBackend::Real_v;
0054 
0055   VECCORE_ATT_HOST_DEVICE
0056   virtual ~VUnplacedVolume() {}
0057 
0058   VECGEOM_FORCE_INLINE
0059   VECCORE_ATT_HOST_DEVICE
0060   void SetBBox(Vector3D<Precision> const &amin, Vector3D<Precision> const &amax)
0061   {
0062     fBBox[0] = amin;
0063     fBBox[1] = amax;
0064   }
0065 
0066   VECGEOM_FORCE_INLINE
0067   VECCORE_ATT_HOST_DEVICE
0068   void GetBBox(Vector3D<Precision> &amin, Vector3D<Precision> &amax) const
0069   {
0070     amin = fBBox[0];
0071     amax = fBBox[1];
0072   }
0073 
0074   VECGEOM_FORCE_INLINE
0075   VECCORE_ATT_HOST_DEVICE
0076   void ComputeBBox()
0077   {
0078 #ifndef VECCORE_CUDA_DEVICE_COMPILATION
0079     Extent(fBBox[0], fBBox[1]);
0080 #endif
0081   }
0082 
0083   // ---------------- Contains --------------------------------------------------------------------
0084 
0085   /*!
0086    * Returns whether a space point pos is contained or not in the shape.
0087    */
0088   VECCORE_ATT_HOST_DEVICE
0089   virtual bool Contains(Vector3D<Precision> const &pos) const = 0;
0090 
0091   /*!
0092    * Returns whether a space point pos is inside, on the surface or outside
0093    * the shape. The surface is defined by a thickness constant.
0094    */
0095   VECCORE_ATT_HOST_DEVICE
0096   virtual EnumInside Inside(Vector3D<Precision> const &pos) const = 0;
0097 
0098   // ---------------- DistanceToOut functions -----------------------------------------------------
0099 
0100   /*!
0101    * Returns the distance from an internal or surface space point pos to the surface
0102    * of the shape along the normalized direction dir.
0103    * Does not have to look for surfaces beyond an optional distance of step_max.
0104    * Calling it with an outside point might result in undefined behaviour.
0105    *
0106    * TODO: Clarify return value in case step_max is non-default.
0107    */
0108   VECCORE_ATT_HOST_DEVICE
0109   virtual Precision DistanceToOut(Vector3D<Precision> const &pos, Vector3D<Precision> const &dir,
0110                                   Precision step_max = kInfLength) const = 0;
0111 
0112   /*!
0113    * Same as DistanceToOut(pos, dir, step_max) but in addition returns
0114    * @param normal The unit normal vector at the point of exit (pointing out tbc)
0115    * @param convex Whether the shape lies in the half-space behind the plane defined by the exit point and the normal.
0116    */
0117   VECCORE_ATT_HOST_DEVICE
0118   virtual Precision DistanceToOut(Vector3D<Precision> const &pos, Vector3D<Precision> const &dir,
0119                                   Vector3D<Precision> &normal, bool &convex, Precision step_max = kInfLength) const;
0120 
0121   /*!
0122    * Same as DistanceToOut(pos, dir, step_max) but treating vectored input/output of type Real_v.
0123    * Real_v represents typically a SIMD register type.
0124    */
0125   VECCORE_ATT_HOST_DEVICE
0126   virtual Real_v DistanceToOutVec(Vector3D<Real_v> const &pos, Vector3D<Real_v> const &dir,
0127                                   Real_v const &step_max) const;
0128 
0129   /*!
0130    * Helper "trampoline" to dispatch to DistanceToOutVec if type is not scalar.
0131    */
0132   template <typename T>
0133   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T DistanceToOut(Vector3D<T> const &p, Vector3D<T> const &d,
0134                                                                T const &step_max) const
0135   {
0136     return DistanceToOutVec(p, d, step_max);
0137   }
0138 
0139   /*!
0140    * Same as DistanceToOut(pos, dir, step_max) but processing a collection of points and directions.
0141    * @param output The vector/container of distances
0142    */
0143   virtual void DistanceToOut(SOA3D<Precision> const &points, SOA3D<Precision> const &directions,
0144                              Precision const *const step_max, Precision *const output) const;
0145 
0146   // ---------------- SafetyToOut functions -----------------------------------------------------
0147 
0148   /*!
0149    * Returns the estimated minimum distance from an internal or surface space point pos to the
0150    * boundary of the shape. The estimate will be strictly smaller or equal to the true value.
0151    * Calling it with an outside point might result in undefined behaviour.
0152    */
0153   VECCORE_ATT_HOST_DEVICE
0154   virtual Precision SafetyToOut(Vector3D<Precision> const &pos) const = 0;
0155 
0156   /*!
0157    * Like SafetToOut(Vector3D<Precision> const &pos) but processing SIMD vector
0158    * input.
0159    */
0160   VECCORE_ATT_HOST_DEVICE
0161   virtual Real_v SafetyToOutVec(Vector3D<Real_v> const &p) const;
0162 
0163   /*!
0164    * Helper trampoline to dispatch to SafetyToOutVec if type is not scalar.
0165    */
0166   template <typename T>
0167   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T SafetyToOut(Vector3D<T> const &p) const
0168   {
0169     return SafetyToOutVec(p);
0170   }
0171 
0172   /*!
0173    * Like SafetyToOut(Vector3D<Precision> const &pos) but processing a collection
0174    * of input points.
0175    */
0176   virtual void SafetyToOut(SOA3D<Precision> const &points, Precision *const output) const /* = 0*/;
0177 
0178   // ---------------- DistanceToIn functions -----------------------------------------------------
0179 
0180   /*!
0181    * Returns the distance from an outside space point pos to the surface
0182    * of the shape along the normalized direction dir.
0183    * Does not have to look for surfaces beyond an optional distance of step_max.
0184    * Calling it with an inside point might result in undefined behaviour.
0185    *
0186    * TODO: Clarify return value in case step_max is non-default.
0187    */
0188   VECCORE_ATT_HOST_DEVICE
0189   virtual Precision DistanceToIn(Vector3D<Precision> const &position, Vector3D<Precision> const &direction,
0190                                  const Precision step_max = kInfLength) const = 0;
0191 
0192   /*!
0193    * Same as DistanceToIn(pos, dir, step_max) but treating vectored input/output of type Real_v.
0194    * Real_v represents typically a SIMD register type.
0195    */
0196   VECCORE_ATT_HOST_DEVICE
0197   virtual Real_v DistanceToInVec(Vector3D<Real_v> const &position, Vector3D<Real_v> const &direction,
0198                                  const Real_v &step_max = Real_v(kInfLength)) const /* = 0 */;
0199 
0200   /*!
0201    * Helper trampoline to dispatch to DistanceToInVec if type is not scalar.
0202    * The T = Precision this template will not instantiate as the compiler finds another matching function
0203    */
0204   template <typename T>
0205   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T DistanceToIn(Vector3D<T> const &p, Vector3D<T> const &d,
0206                                                               T const &step_max) const
0207   {
0208     return DistanceToInVec(p, d, step_max);
0209   }
0210 
0211   // ---------------- SafetyToIn functions -------------------------------------------------------
0212 
0213   /*!
0214    * Returns the estimated minimum distance from an outside or surface space point pos to the
0215    * boundary of the shape. The estimate will be strictly smaller or equal to the true value.
0216    * Calling it with an inside point is undefined behaviour.
0217    */
0218   VECCORE_ATT_HOST_DEVICE
0219   virtual Precision SafetyToIn(Vector3D<Precision> const &pos) const = 0;
0220 
0221   /*!
0222    * Like SafetyToIn(Vector3D<Precision> const &) but processing SIMD vector
0223    * input.
0224    */
0225   VECCORE_ATT_HOST_DEVICE
0226   virtual Real_v SafetyToInVec(Vector3D<Real_v> const &p) const;
0227 
0228   /*!
0229    *  Helper trampoline to dispatch to SafetyToInVec if type is not scalar.
0230    */
0231   template <typename T>
0232   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE T SafetyToIn(Vector3D<T> const &p) const
0233   {
0234     return SafetyToInVec(p);
0235   }
0236 
0237   // ---------------- Normal ---------------------------------------------------------------------
0238 
0239   /*!
0240    * Calculates the surface normal unit vector for a space point pos, assuming
0241    * that pos is on the surface (i.e. Inside(pos) == kSurface).
0242    * The behaviour for a point not on the surface is undefined.
0243    * TODO: Clarify whether normal always points outwards.
0244    */
0245   VECCORE_ATT_HOST_DEVICE
0246   virtual bool Normal(Vector3D<Precision> const &pos, Vector3D<Precision> &normal) const /* = 0 */;
0247 
0248   // ---------------- SamplePointOnSurface ----------------------------------------------------------
0249   /*!
0250    * Generates random point pos on the surface of the shape.
0251    * The returned point satisfies Inside(pos)==kSurface.
0252    */
0253   virtual Vector3D<Precision> SamplePointOnSurface() const /* = 0 */;
0254 
0255   // ----------------- Extent --------------------------------------------------------------------
0256 
0257   /*!
0258    * Returns the extent of the shape as corner points of the enclosing
0259    * bounding box.
0260    * @param aMin point of bounding box corner with minimum coordinates
0261    * @param aMax point of bounding box corner with maximum coordinates
0262    */
0263   VECCORE_ATT_HOST_DEVICE
0264   virtual void Extent(Vector3D<Precision> &aMin, Vector3D<Precision> &aMax) const /* = 0 */;
0265 
0266   VECGEOM_FORCE_INLINE
0267   VECCORE_ATT_HOST_DEVICE
0268   Precision ApproachSolid(Vector3D<Precision> const &point, Vector3D<Precision> const &invDir) const
0269   {
0270     Precision distance = BoxImplementation::IntersectCachedKernel2<Precision, Precision>(
0271         fBBox, point, invDir, invDir.x() < 0, invDir.y() < 0, invDir.z() < 0, 0, kInfLength);
0272     return vecCore::math::Max(distance, Precision(0));
0273   }
0274 
0275   /*!
0276    *  Returns whether the shape is (globally) convex or not.
0277    *  If not known, returns false.
0278    */
0279   VECCORE_ATT_HOST_DEVICE
0280   bool IsConvex() const { return fGlobalConvexity; }
0281 
0282   /*!
0283    *  Returns whether the shape is an assembly
0284    */
0285   VECCORE_ATT_HOST_DEVICE
0286   bool IsAssembly() const { return fIsAssembly; }
0287 
0288   // ----------------- Capacity --------------------------------------------------------------------
0289   /*!
0290    *  Returns the (exact or estimated) cubic volume/capacity of the shape.
0291    */
0292   virtual Precision Capacity() const = 0;
0293 
0294   /*!
0295    *  Calculates an estimate of the cubic volume of the shape via a sampling technique.
0296    *  @param nStat number of sample points to be used
0297    */
0298   Precision EstimateCapacity(int nStat = 100000) const;
0299 
0300   // ----------------- Surface Area ----------------------------------------------------------------
0301   /*!
0302    *  Returns the (exact or estimated) surface area of the shape.
0303    */
0304   virtual Precision SurfaceArea() const = 0;
0305 
0306   /*!
0307    *  Calculates an estimate of the surface area of the shape via a sampling technique.
0308    *  @param nStat number of sample points to be used
0309    */
0310   Precision EstimateSurfaceArea(int nStat = 100000) const;
0311 
0312   /*!
0313    * Standard output operator for a textual representation.
0314    * (Uses the virtual method print(std::ostream &ps))
0315    */
0316   friend std::ostream &operator<<(std::ostream &os, VUnplacedVolume const &vol);
0317 
0318   /*!
0319    * Return the size of the deriving class in bytes. Necessary for
0320    * copying to the GPU.
0321    */
0322   virtual int MemorySize() const = 0;
0323 
0324 #ifdef VECGEOM_CUDA_INTERFACE
0325   virtual size_t DeviceSizeOf() const = 0;
0326 
0327   /*!
0328    * Constructs the deriving class on the GPU and returns a pointer to GPU
0329    * memory where the object has been instantiated.
0330    */
0331   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const                                               = 0;
0332   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const = 0;
0333 
0334   template <typename Derived, typename... ArgsTypes>
0335   DevicePtr<cuda::VUnplacedVolume> CopyToGpuImpl(DevicePtr<cuda::VUnplacedVolume> const in_gpu_ptr,
0336                                                  ArgsTypes... params) const
0337   {
0338     DevicePtr<CudaType_t<Derived>> gpu_ptr(in_gpu_ptr);
0339     gpu_ptr.Construct(params...);
0340     CudaAssertError();
0341     // Need to go via the void* because the regular c++ compilation
0342     // does not actually see the declaration for the cuda version
0343     // (and thus can not determine the inheritance).
0344     return DevicePtr<cuda::VUnplacedVolume>((void *)gpu_ptr);
0345   }
0346   template <typename Derived>
0347   DevicePtr<cuda::VUnplacedVolume> CopyToGpuImpl() const
0348   {
0349     DevicePtr<CudaType_t<Derived>> gpu_ptr;
0350     gpu_ptr.Allocate();
0351     return this->CopyToGpu(DevicePtr<cuda::VUnplacedVolume>((void *)gpu_ptr));
0352   }
0353 
0354   static void CopyBBoxesToGpu(const std::vector<VUnplacedVolume const *> &volumes,
0355                               const std::vector<DevicePtr<cuda::VUnplacedVolume>> &gpu_ptrs);
0356 
0357 #endif
0358 
0359   /*!
0360    * Print a textual representation of the shape to a given outstream os.
0361    * This should typically tell the parameters, class, etc. of the shape.
0362    */
0363   virtual void Print(std::ostream &os) const = 0;
0364 
0365   /**
0366    * C-style printing for CUDA purposes.
0367    * TODO: clarify relation to other Print.
0368    */
0369   VECCORE_ATT_HOST_DEVICE
0370   virtual void Print() const = 0;
0371 
0372 /// Generates mesh representation of the solid
0373 #ifndef VECCORE_CUDA
0374   virtual SolidMesh *CreateMesh3D(Transformation3D const & /*trans*/, const size_t /*nSegments*/) const
0375   {
0376     return nullptr;
0377   };
0378 #endif
0379 
0380   // Is not static because a virtual function must be called to initialize
0381   // specialized volume as the shape of the deriving class.
0382   // TODO: clarify
0383   VPlacedVolume *PlaceVolume(char const *const label, LogicalVolume const *const volume,
0384                              Transformation3D const *const transformation, VPlacedVolume *const placement = NULL) const;
0385 
0386   VPlacedVolume *PlaceVolume(LogicalVolume const *const volume, Transformation3D const *const transformation,
0387                              VPlacedVolume *const placement = NULL) const;
0388 
0389 private:
0390 #ifndef VECCORE_CUDA
0391 
0392   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0393                                            Transformation3D const *const transformation,
0394                                            const TranslationCode trans_code, const RotationCode rot_code,
0395                                            VPlacedVolume *const placement = NULL) const = 0;
0396 
0397 #else
0398   VECCORE_ATT_DEVICE
0399   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0400                                            Transformation3D const *const transformation,
0401                                            const TranslationCode trans_code, const RotationCode rot_code, const int id,
0402                                            const int copy_no, const int child_id,
0403                                            VPlacedVolume *const placement = NULL) const = 0;
0404 
0405 #endif
0406 };
0407 
0408 /*!
0409  * A template structure used to create specialized instances
0410  * of a shape. Used by the shape factory mechanism.
0411  */
0412 template <typename Shape_t>
0413 struct Maker {
0414   template <typename... ArgTypes>
0415   static Shape_t *MakeInstance(ArgTypes... args)
0416   {
0417     // the default case calls the standard constructor
0418     return new Shape_t(args...);
0419   }
0420 };
0421 
0422 std::ostream &operator<<(std::ostream &os, VUnplacedVolume const &vol);
0423 
0424 } // namespace VECGEOM_IMPL_NAMESPACE
0425 
0426 } // namespace vecgeom
0427 
0428 #endif // VECGEOM_VOLUMES_UNPLACEDVOLUME_H_