Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-19 09:40:43

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/Assert.h"
0013 #include "VecGeom/base/Cuda.h"
0014 #include "VecGeom/base/Global.h"
0015 #include "VecGeom/base/Transformation3D.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   VECCORE_ATT_HOST_DEVICE
0053   virtual ~VUnplacedVolume() {}
0054 
0055   VECCORE_ATT_HOST_DEVICE
0056   virtual bool IsBoolean() const { return false; }
0057 
0058   VECCORE_ATT_HOST_DEVICE
0059   VECGEOM_FORCE_INLINE
0060   virtual ESolidType GetType() const { return ESolidType::nosolid; }
0061 
0062   VECGEOM_FORCE_INLINE
0063   VECCORE_ATT_HOST_DEVICE
0064   void SetBBox(Vector3D<Precision> const &amin, Vector3D<Precision> const &amax)
0065   {
0066     fBBox[0] = amin;
0067     fBBox[1] = amax;
0068   }
0069 
0070   VECGEOM_FORCE_INLINE
0071   VECCORE_ATT_HOST_DEVICE
0072   void GetBBox(Vector3D<Precision> &amin, Vector3D<Precision> &amax) const
0073   {
0074     amin = fBBox[0];
0075     amax = fBBox[1];
0076   }
0077 
0078   VECGEOM_FORCE_INLINE
0079   VECCORE_ATT_HOST_DEVICE
0080   void ComputeBBox()
0081   {
0082 #ifndef VECCORE_CUDA_DEVICE_COMPILATION
0083     Extent(fBBox[0], fBBox[1]);
0084 #endif
0085   }
0086 
0087   // ---------------- Contains --------------------------------------------------------------------
0088 
0089   /*!
0090    * Returns whether a space point pos is contained or not in the shape.
0091    */
0092   VECCORE_ATT_HOST_DEVICE
0093   virtual bool Contains(Vector3D<Precision> const &pos) const = 0;
0094 
0095   /*!
0096    * Returns whether a space point pos is inside, on the surface or outside
0097    * the shape. The surface is defined by a thickness constant.
0098    */
0099   VECCORE_ATT_HOST_DEVICE
0100   virtual EnumInside Inside(Vector3D<Precision> const &pos) const = 0;
0101 
0102   // ---------------- DistanceToOut functions -----------------------------------------------------
0103 
0104   /*!
0105    * Returns the distance from an internal or surface space point pos to the surface
0106    * of the shape along the normalized direction dir.
0107    * Does not have to look for surfaces beyond an optional distance of step_max.
0108    * Calling it with an outside point might result in undefined behaviour.
0109    *
0110    * TODO: Clarify return value in case step_max is non-default.
0111    */
0112   VECCORE_ATT_HOST_DEVICE
0113   virtual Precision DistanceToOut(Vector3D<Precision> const &pos, Vector3D<Precision> const &dir,
0114                                   Precision step_max = kInfLength) const = 0;
0115 
0116   // ---------------- SafetyToOut functions -----------------------------------------------------
0117 
0118   /*!
0119    * Returns the estimated minimum distance from an internal or surface space point pos to the
0120    * boundary of the shape. The estimate will be strictly smaller or equal to the true value.
0121    * Calling it with an outside point might result in undefined behaviour.
0122    */
0123   VECCORE_ATT_HOST_DEVICE
0124   virtual Precision SafetyToOut(Vector3D<Precision> const &pos) const = 0;
0125 
0126   // ---------------- DistanceToIn functions -----------------------------------------------------
0127 
0128   /*!
0129    * Returns the distance from an outside space point pos to the surface
0130    * of the shape along the normalized direction dir.
0131    * Does not have to look for surfaces beyond an optional distance of step_max.
0132    * Calling it with an inside point might result in undefined behaviour.
0133    *
0134    * TODO: Clarify return value in case step_max is non-default.
0135    */
0136   VECCORE_ATT_HOST_DEVICE
0137   virtual Precision DistanceToIn(Vector3D<Precision> const &position, Vector3D<Precision> const &direction,
0138                                  const Precision step_max = kInfLength) const = 0;
0139 
0140   // ---------------- SafetyToIn functions -------------------------------------------------------
0141 
0142   /*!
0143    * Returns the estimated minimum distance from an outside or surface space point pos to the
0144    * boundary of the shape. The estimate will be strictly smaller or equal to the true value.
0145    * Calling it with an inside point is undefined behaviour.
0146    */
0147   VECCORE_ATT_HOST_DEVICE
0148   virtual Precision SafetyToIn(Vector3D<Precision> const &pos) const = 0;
0149 
0150   // ---------------- Normal ---------------------------------------------------------------------
0151 
0152   /*!
0153    * Calculates the surface normal unit vector for a space point pos, assuming
0154    * that pos is on the surface (i.e. Inside(pos) == kSurface).
0155    * The behaviour for a point not on the surface is undefined.
0156    * TODO: Clarify whether normal always points outwards.
0157    */
0158   VECCORE_ATT_HOST_DEVICE
0159   virtual bool Normal(Vector3D<Precision> const &pos, Vector3D<Precision> &normal) const = 0;
0160 
0161   // ---------------- SamplePointOnSurface ----------------------------------------------------------
0162   /*!
0163    * Generates random point pos on the surface of the shape.
0164    * The returned point satisfies Inside(pos)==kSurface.
0165    */
0166   virtual Vector3D<Precision> SamplePointOnSurface() const /* = 0 */;
0167 
0168   // ----------------- Extent --------------------------------------------------------------------
0169 
0170   /*!
0171    * Returns the extent of the shape as corner points of the enclosing
0172    * bounding box.
0173    * @param aMin point of bounding box corner with minimum coordinates
0174    * @param aMax point of bounding box corner with maximum coordinates
0175    */
0176   VECCORE_ATT_HOST_DEVICE
0177   virtual void Extent(Vector3D<Precision> &aMin, Vector3D<Precision> &aMax) const = 0;
0178 
0179   VECGEOM_FORCE_INLINE
0180   VECCORE_ATT_HOST_DEVICE
0181   Precision ApproachSolid(Vector3D<Precision> const &point, Vector3D<Precision> const &invDir) const
0182   {
0183     Precision distance = BoxImplementation::IntersectCachedKernel2<Precision, Precision>(
0184         fBBox, point, invDir, invDir.x() < 0, invDir.y() < 0, invDir.z() < 0, 0, kInfLength);
0185     return vecCore::math::Max(distance, Precision(0));
0186   }
0187 
0188   /*!
0189    *  Returns whether the shape is (globally) convex or not.
0190    *  If not known, returns false.
0191    */
0192   VECCORE_ATT_HOST_DEVICE
0193   bool IsConvex() const { return fGlobalConvexity; }
0194 
0195   /*!
0196    *  Returns whether the shape is an assembly
0197    */
0198   VECCORE_ATT_HOST_DEVICE
0199   bool IsAssembly() const { return fIsAssembly; }
0200 
0201   // ----------------- Capacity --------------------------------------------------------------------
0202   /*!
0203    *  Returns the (exact or estimated) cubic volume/capacity of the shape.
0204    */
0205   virtual Precision Capacity() const = 0;
0206 
0207   /*!
0208    *  Calculates an estimate of the cubic volume of the shape via a sampling technique.
0209    *  @param nStat number of sample points to be used
0210    */
0211   Precision EstimateCapacity(int nStat = 100000) const;
0212 
0213   // ----------------- Surface Area ----------------------------------------------------------------
0214   /*!
0215    *  Returns the (exact or estimated) surface area of the shape.
0216    */
0217   virtual Precision SurfaceArea() const = 0;
0218 
0219   /*!
0220    *  Calculates an estimate of the surface area of the shape via a sampling technique.
0221    *  @param nStat number of sample points to be used
0222    */
0223   Precision EstimateSurfaceArea(int nStat = 100000) const;
0224 
0225   /*!
0226    * Standard output operator for a textual representation.
0227    * (Uses the virtual method print(std::ostream &ps))
0228    */
0229   friend std::ostream &operator<<(std::ostream &os, VUnplacedVolume const &vol);
0230 
0231   /*!
0232    * Return the size of the deriving class in bytes. Necessary for
0233    * copying to the GPU.
0234    */
0235   virtual int MemorySize() const = 0;
0236 
0237 #ifdef VECGEOM_CUDA_INTERFACE
0238   virtual size_t DeviceSizeOf() const = 0;
0239 
0240   /*!
0241    * Constructs the deriving class on the GPU and returns a pointer to GPU
0242    * memory where the object has been instantiated.
0243    */
0244   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const                                               = 0;
0245   virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const = 0;
0246 
0247   template <typename Derived, typename... ArgsTypes>
0248   DevicePtr<cuda::VUnplacedVolume> CopyToGpuImpl(DevicePtr<cuda::VUnplacedVolume> const in_gpu_ptr,
0249                                                  ArgsTypes... params) const
0250   {
0251     DevicePtr<CudaType_t<Derived>> gpu_ptr(in_gpu_ptr);
0252     gpu_ptr.Construct(params...);
0253     VECGEOM_DEVICE_API_CALL(GetLastError());
0254     // Need to go via the void* because the regular c++ compilation
0255     // does not actually see the declaration for the cuda version
0256     // (and thus can not determine the inheritance).
0257     return DevicePtr<cuda::VUnplacedVolume>((void *)gpu_ptr);
0258   }
0259   template <typename Derived>
0260   DevicePtr<cuda::VUnplacedVolume> CopyToGpuImpl() const
0261   {
0262     DevicePtr<CudaType_t<Derived>> gpu_ptr;
0263     gpu_ptr.Allocate();
0264     return this->CopyToGpu(DevicePtr<cuda::VUnplacedVolume>((void *)gpu_ptr));
0265   }
0266 
0267   static void CopyBBoxesToGpu(const std::vector<VUnplacedVolume const *> &volumes,
0268                               const std::vector<DevicePtr<cuda::VUnplacedVolume>> &gpu_ptrs);
0269 
0270 #endif
0271 
0272   /*!
0273    * Print a textual representation of the shape to a given outstream os.
0274    * This should typically tell the parameters, class, etc. of the shape.
0275    */
0276   virtual void Print(std::ostream &os) const = 0;
0277 
0278   /**
0279    * C-style printing for CUDA purposes.
0280    * TODO: clarify relation to other Print.
0281    */
0282   VECCORE_ATT_HOST_DEVICE
0283   virtual void Print() const = 0;
0284 
0285 /// Generates mesh representation of the solid
0286 #ifndef VECCORE_CUDA
0287   virtual SolidMesh *CreateMesh3D(Transformation3D const & /*trans*/, const size_t /*nSegments*/) const
0288   {
0289     return nullptr;
0290   };
0291 #endif
0292 
0293   // Is not static because a virtual function must be called to initialize
0294   // specialized volume as the shape of the deriving class.
0295   // TODO: clarify
0296   VPlacedVolume *PlaceVolume(char const *const label, LogicalVolume const *const volume,
0297                              Transformation3D const *const transformation, VPlacedVolume *const placement = NULL) const;
0298 
0299   VPlacedVolume *PlaceVolume(LogicalVolume const *const volume, Transformation3D const *const transformation,
0300                              VPlacedVolume *const placement = NULL) const;
0301 
0302 private:
0303 #ifndef VECCORE_CUDA
0304 
0305   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0306                                            Transformation3D const *const transformation,
0307                                            VPlacedVolume *const placement = NULL) const = 0;
0308 
0309 #else
0310   VECCORE_ATT_DEVICE
0311   virtual VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
0312                                            Transformation3D const *const transformation, const int id,
0313                                            const int copy_no, const int child_id,
0314                                            VPlacedVolume *const placement = NULL) const = 0;
0315 
0316 #endif
0317 };
0318 
0319 /*!
0320  * A template structure used to create specialized instances
0321  * of a shape. Used by the shape factory mechanism.
0322  */
0323 template <typename Shape_t>
0324 struct Maker {
0325   template <typename... ArgTypes>
0326   static Shape_t *MakeInstance(ArgTypes... args)
0327   {
0328     // the default case calls the standard constructor
0329     return new Shape_t(args...);
0330   }
0331 };
0332 
0333 std::ostream &operator<<(std::ostream &os, VUnplacedVolume const &vol);
0334 
0335 } // namespace VECGEOM_IMPL_NAMESPACE
0336 
0337 } // namespace vecgeom
0338 
0339 #endif // VECGEOM_VOLUMES_UNPLACEDVOLUME_H_