Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:26:19

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 /// \file PlacedVolume.h
0006 /// \author created by Johannes de Fine Licht, Sandro Wenzel (CERN)
0007 
0008 #ifndef VECGEOM_VOLUMES_PLACEDVOLUME_H_
0009 #define VECGEOM_VOLUMES_PLACEDVOLUME_H_
0010 
0011 #include "VecGeom/base/Cuda.h"
0012 #include "VecGeom/base/Global.h"
0013 #include "VecGeom/volumes/LogicalVolume.h"
0014 #include <string>
0015 
0016 #ifdef VECGEOM_GEANT4
0017 #include <G4VSolid.hh>
0018 #endif
0019 
0020 using Real_v = vecgeom::VectorBackend::Real_v;
0021 
0022 namespace vecgeom {
0023 
0024 VECGEOM_DEVICE_FORWARD_DECLARE(class VPlacedVolume;);
0025 VECGEOM_DEVICE_DECLARE_CONV(class, VPlacedVolume);
0026 #ifndef VECCORE_CUDA
0027 template <>
0028 struct kCudaType<const cxx::VPlacedVolume *> {
0029   using type_t = const cuda::VPlacedVolume *;
0030 };
0031 #endif
0032 
0033 inline namespace VECGEOM_IMPL_NAMESPACE {
0034 
0035 class PlacedBox;
0036 class GeoManager;
0037 template <typename T>
0038 class SOA3D;
0039 
0040 /*!
0041  * \brief A placed volume is a positioned logical volume.
0042  *
0043  * Special features of VecGeom are that:
0044  *
0045  *   1. Placed volumes offer
0046  *      similar geometry interfaces (distance, etc) as unplaced volumes for user convenience.
0047  *   2. We can have sub-types of placed volumes, specialized according
0048  *      to underlying unplaced volume type as well as per categories
0049  *      of placing transformations.
0050  *
0051  * Given a logical volume and a transformation, factory methods
0052  * will generate the most suitable sub-type of a placed volume so that
0053  * geometry APIs, such as VPlacedVolume::DistanceToIn(position, direction)
0054  * are optimized as much as possible. Some CMake flags allow to select how
0055  * far this is done or not.
0056  */
0057 class VPlacedVolume {
0058   friend class GeoManager;
0059 
0060 private:
0061   unsigned int id_;  ///< Integer id
0062   int copy_no_ = 0;  ///< Copy number for the physical volume, used by transport
0063   int ichild_  = -1; ///< Index in the mother volume list;
0064 
0065   // Use a pointer so the string won't be constructed on the GPU
0066   std::string *label_;            ///< Label/name of placed volume
0067   static unsigned int g_id_count; ///< Static instance counter
0068 
0069 protected:
0070   LogicalVolume const *logical_volume_; ///< Pointer to positioned logical volume
0071 #ifdef VECGEOM_INPLACE_TRANSFORMATIONS
0072   Transformation3D fTransformation; ///< The positioning transformation
0073 #else
0074   Transformation3D const *fTransformation; ///< The positioning transformation
0075 #endif
0076 
0077 #ifndef VECCORE_CUDA
0078 
0079   /** Constructor
0080    * \param label Name of logical volume.
0081    * \param logical_vol The logical volume to be positioned.
0082    * \param transform The positioning transformation.
0083    */
0084   VPlacedVolume(char const *const label, LogicalVolume const *const logical_vol,
0085                 Transformation3D const *const transform);
0086 
0087   /** Constructor
0088    * \param logical_vol The logical volume to be positioned.
0089    * \param transform The positioning transformation.
0090    */
0091   VPlacedVolume(LogicalVolume const *const logical_vol, Transformation3D const *const transform)
0092       : VPlacedVolume("", logical_vol, transform)
0093   {
0094   }
0095 
0096 #else
0097   /// CUDA version of constructor
0098   VECCORE_ATT_DEVICE VPlacedVolume(LogicalVolume const *const logical_vol, Transformation3D const *const transformation,
0099                                    unsigned int id, int copy_no, int ichild)
0100 #ifdef VECGEOM_INPLACE_TRANSFORMATIONS
0101       : logical_volume_(logical_vol), fTransformation(*transformation), id_(id), copy_no_(copy_no), ichild_(ichild),
0102         label_(NULL)
0103   {
0104   }
0105 #else
0106       : logical_volume_(logical_vol), fTransformation(transformation), id_(id), copy_no_(copy_no), ichild_(ichild),
0107         label_(NULL)
0108   {
0109   }
0110 #endif
0111 #endif
0112 
0113   VECGEOM_FORCE_INLINE
0114   void SetChildId(int index) { ichild_ = index; }
0115 
0116 public:
0117   VECCORE_ATT_HOST_DEVICE
0118   VPlacedVolume(VPlacedVolume const &);
0119   VECCORE_ATT_HOST_DEVICE
0120   VPlacedVolume *operator=(VPlacedVolume const &);
0121 
0122   VECCORE_ATT_HOST_DEVICE
0123   virtual ~VPlacedVolume();
0124 
0125   /// Returns integer index associated to this volume.
0126   VECCORE_ATT_HOST_DEVICE
0127   VECGEOM_FORCE_INLINE
0128   unsigned int id() const { return id_; }
0129 
0130   /// Returns copy number.
0131   VECCORE_ATT_HOST_DEVICE
0132   VECGEOM_FORCE_INLINE
0133   int GetChildId() const { return ichild_; }
0134 
0135   /// LogicalVolume::PlaceDaughters is a friend that can set the child index
0136   friend void LogicalVolume::PlaceDaughter(VPlacedVolume *const placed);
0137 
0138   /// Returns copy number.
0139   VECCORE_ATT_HOST_DEVICE
0140   VECGEOM_FORCE_INLINE
0141   int GetCopyNo() const { return copy_no_; }
0142 
0143   /// Returns value of static instance counter
0144   static unsigned int GetIdCount() { return g_id_count; }
0145 
0146   /// Returns name/label.
0147   std::string const &GetLabel() const { return *label_; }
0148 
0149   /// Returns underlying logical volume.
0150   VECCORE_ATT_HOST_DEVICE
0151   VECGEOM_FORCE_INLINE
0152   LogicalVolume const *GetLogicalVolume() const { return logical_volume_; }
0153 
0154   /// Returns daughter container of logical volume.
0155   VECCORE_ATT_HOST_DEVICE
0156   VECGEOM_FORCE_INLINE
0157   Vector<Daughter> const &GetDaughters() const { return logical_volume_->GetDaughters(); }
0158 
0159   /// Finds the index of a given daughter having its pointer (linear complexity)
0160   VECCORE_ATT_HOST_DEVICE
0161   VECGEOM_FORCE_INLINE
0162   int IndexOf(Daughter daughter) const
0163   {
0164     int id = 0;
0165     for (auto d : logical_volume_->GetDaughters()) {
0166       if (d == daughter) return id;
0167       id++;
0168     }
0169     return -1;
0170   }
0171 
0172   /// Returns name/label.
0173   VECCORE_ATT_HOST
0174   VECGEOM_FORCE_INLINE
0175   const char *GetName() const { return (*label_).c_str(); }
0176 
0177   /// Returns unplaced volume encapsulated in the logical volume.
0178   VECCORE_ATT_HOST_DEVICE
0179   VECGEOM_FORCE_INLINE
0180   VUnplacedVolume const *GetUnplacedVolume() const { return logical_volume_->GetUnplacedVolume(); }
0181 
0182   /// Returns if underlying unplaced volume is an assembly.
0183   VECCORE_ATT_HOST_DEVICE
0184   bool IsAssembly() const { return GetUnplacedVolume()->IsAssembly(); }
0185 
0186   /// Returns underlying transformation.
0187   VECCORE_ATT_HOST_DEVICE
0188   VECGEOM_FORCE_INLINE
0189   Transformation3D const *GetTransformation() const
0190   {
0191 #ifdef VECGEOM_INPLACE_TRANSFORMATIONS
0192     return &fTransformation;
0193 #else
0194     return fTransformation;
0195 #endif
0196   }
0197 #ifndef VECCORE_CUDA
0198   SolidMesh *CreateMesh3D(size_t nFaces) const
0199   {
0200     return GetUnplacedVolume()->CreateMesh3D(*this->GetTransformation(), nFaces);
0201   }
0202 #endif
0203   /// Sets logical volume.
0204   VECCORE_ATT_HOST_DEVICE
0205   void SetLogicalVolume(LogicalVolume const *const logical_vol) { logical_volume_ = logical_vol; }
0206 
0207   /// Sets transformation.
0208   VECCORE_ATT_HOST_DEVICE
0209   void SetTransformation(Transformation3D const *const transform)
0210   {
0211 #ifdef VECGEOM_INPLACE_TRANSFORMATIONS
0212     fTransformation = *transform;
0213 #else
0214     fTransformation = transform;
0215 #endif
0216   }
0217 
0218   /// Sets name/label.
0219   void set_label(char const *label)
0220   {
0221     if (label_) delete label_;
0222     label_ = new std::string(label);
0223   }
0224 
0225   /// Sets copy number.
0226   VECCORE_ATT_HOST_DEVICE
0227   VECGEOM_FORCE_INLINE
0228   void SetCopyNo(int copy_no) { copy_no_ = copy_no; }
0229 
0230   friend std::ostream &operator<<(std::ostream &os, VPlacedVolume const &vol);
0231 
0232   /// Returns in-memory size in bytes of deriving objects (used to copy to GPU).
0233   virtual int MemorySize() const = 0;
0234 
0235   /// Print info about placed volume.
0236   VECCORE_ATT_HOST_DEVICE
0237   virtual void Print(const int indent = 0) const;
0238 
0239   /// Print info about placed volume.
0240   VECCORE_ATT_HOST_DEVICE
0241   virtual void PrintType() const = 0;
0242 
0243   // some functions allowing for some very basic "introspection"
0244 
0245   /// Print the actual volume type to an outstream
0246   virtual void PrintType(std::ostream &os) const = 0;
0247   /// Print the implementation struct of this volume to an outstream
0248   virtual void PrintImplementationType(std::ostream &os) const = 0;
0249   /// Print the unplaced type to an outstream
0250   virtual void PrintUnplacedType(std::ostream &os) const = 0;
0251 
0252   /// Returns translation code/enumeration of the placed volume
0253   virtual int GetTransCode() const { return translation::kGeneric; }
0254 
0255   /// Returns rotation code/enumeration of the placed volume
0256   virtual int GetRotCode() const { return rotation::kGeneric; }
0257 
0258   /// Recursively prints contained volumes to standard output.
0259   VECCORE_ATT_HOST_DEVICE
0260   void PrintContent(const int depth = 0) const;
0261 
0262   // Geometry functionality like in unplaced volume but taking the placement
0263   // into account.
0264 
0265   /*!
0266    * Returns whether a space point is contained or not in the placed volume.
0267    * This is similar to the functionality in VUnplacedVolume but taking into account
0268    * the positioning of the shape due to the placement.
0269    */
0270   VECCORE_ATT_HOST_DEVICE
0271   virtual bool Contains(Vector3D<Precision> const &point) const = 0;
0272 
0273   virtual void Contains(SOA3D<Precision> const &point, bool *const output) const = 0;
0274 
0275   /*!
0276    * Returns whether a space point is contained or not in the placed volume.
0277    * Also returns the transformed position.
0278    *
0279    * \param point A given space point.
0280    * \param localPoint The point in the natural reference frame of the shape.
0281    *
0282    * This is similar to the functionality in VUnplacedVolume but taking into account
0283    * the positioning of the shape due to the placement.
0284    */
0285   VECCORE_ATT_HOST_DEVICE
0286   virtual bool Contains(Vector3D<Precision> const &point, Vector3D<Precision> &localPoint) const = 0;
0287 
0288   /// Direct dispatch to Contains of underlying unplaced volume without coordinate/placement transformation.
0289   VECCORE_ATT_HOST_DEVICE
0290   virtual bool UnplacedContains(Vector3D<Precision> const &localPoint) const = 0;
0291 
0292   /**
0293    * Like similar function in VUnplacedVolume but taking into account
0294    * the positioning of the shape due to the placement.
0295    */
0296   VECCORE_ATT_HOST_DEVICE
0297   virtual EnumInside Inside(Vector3D<Precision> const &point) const = 0;
0298 
0299   virtual void Inside(SOA3D<Precision> const &point, Inside_t *const output) const = 0;
0300 
0301   /**
0302    * Like similar function in VUnplacedVolume but taking into account
0303    * the positioning of the shape due to the placement.
0304    */
0305   VECCORE_ATT_HOST_DEVICE
0306   virtual Precision DistanceToIn(Vector3D<Precision> const &position, Vector3D<Precision> const &direction,
0307                                  const Precision step_max = kInfLength) const = 0;
0308 
0309   /**
0310    * Like similar function in VUnplacedVolume but taking into account
0311    * the positioning of the shape due to the placement.
0312    */
0313   // if we have any SIMD backend, we offer a SIMD interface
0314   virtual Real_v DistanceToInVec(Vector3D<Real_v> const &position, Vector3D<Real_v> const &direction,
0315                                  const Real_v step_max = kInfLength) const = 0;
0316 
0317   /**
0318    * Like similar function in VUnplacedVolume but taking into account
0319    * the positioning of the shape due to the placement.
0320    */
0321   template <typename T>
0322   VECGEOM_FORCE_INLINE T DistanceToIn(Vector3D<T> const &position, Vector3D<T> const &direction,
0323                                       const T step_max = T(kInfLength)) const
0324   {
0325     return DistanceToInVec(position, direction, step_max);
0326   }
0327 
0328   /**
0329    * Like similar function in VUnplacedVolume but taking into account
0330    * the positioning of the shape due to the placement.
0331    */
0332   virtual void DistanceToIn(SOA3D<Precision> const &position, SOA3D<Precision> const &direction,
0333                             Precision const *const step_max, Precision *const output) const = 0;
0334 
0335   /**
0336    * Like similar function in VUnplacedVolume. Here position and direction are supposed to be
0337    * in the frame of the placed volume!
0338    */
0339   VECCORE_ATT_HOST_DEVICE
0340   virtual Precision DistanceToOut(Vector3D<Precision> const &position, Vector3D<Precision> const &direction,
0341                                   Precision const step_max = kInfLength) const = 0;
0342 
0343   /**
0344    * Like similar function in VUnplacedVolume. Here position and direction are supposed to be
0345    * in the frame of the placed volume!
0346    */
0347   virtual Real_v DistanceToOutVec(Vector3D<Real_v> const &position, Vector3D<Real_v> const &direction,
0348                                   Real_v const step_max = kInfLength) const = 0;
0349 
0350   /**
0351    * Like similar function in VUnplacedVolume. Here position and direction are supposed to be
0352    * in the frame of the placed volume!
0353    */
0354   template <typename T>
0355   VECGEOM_FORCE_INLINE T DistanceToOut(Vector3D<T> const &position, Vector3D<T> const &direction,
0356                                        const T step_max = T(kInfLength)) const
0357   {
0358     return DistanceToOutVec(position, direction, step_max);
0359   }
0360 
0361   /** A "placed" version of the DistanceToOut function; here
0362    * the point and direction are first of all transformed into the reference frame of the
0363    * shape. So given a position and direction in the reference frame in which the placed volume
0364    * is positioned, we transform everything into the coordinate system of the placed volume and
0365    * calculate DistanceToOut from there.
0366    */
0367   VECCORE_ATT_HOST_DEVICE
0368   virtual Precision PlacedDistanceToOut(Vector3D<Precision> const &position, Vector3D<Precision> const &direction,
0369                                         Precision const step_max = kInfLength) const = 0;
0370 
0371   /// to be deprecated
0372   virtual void DistanceToOut(SOA3D<Precision> const &position, SOA3D<Precision> const &direction,
0373                              Precision const *const step_max, Precision *const output) const = 0;
0374 
0375   /// to be deprecated
0376   virtual void DistanceToOut(SOA3D<Precision> const &position, SOA3D<Precision> const &direction,
0377                              Precision const *const step_max, Precision *const output,
0378                              int *const nextnodeindex) const = 0;
0379 
0380   /**
0381    * Like similar function in VUnplacedVolume but taking into account
0382    * the positioning of the shape due to the placement.
0383    */
0384   VECCORE_ATT_HOST_DEVICE
0385   virtual Precision SafetyToIn(Vector3D<Precision> const &position) const = 0;
0386 
0387   /**
0388    * Like similar function in VUnplacedVolume but taking into account
0389    * the positioning of the shape due to the placement.
0390    */
0391   virtual Real_v SafetyToInVec(Vector3D<Real_v> const &position) const = 0;
0392 
0393   /**
0394    * Like similar function in VUnplacedVolume but taking into account
0395    * the positioning of the shape due to the placement.
0396    */
0397   template <typename T>
0398   VECGEOM_FORCE_INLINE T SafetyToIn(Vector3D<T> const &p) const
0399   {
0400     return SafetyToInVec(p);
0401   }
0402 
0403   /// to be deprecated
0404   virtual void SafetyToIn(SOA3D<Precision> const &position, Precision *const safeties) const = 0;
0405 
0406   /**
0407    * Like similar function in VUnplacedVolume. Here position is supposed to be
0408    * in the frame of the placed volume.
0409    */
0410   VECCORE_ATT_HOST_DEVICE
0411   virtual Precision SafetyToOut(Vector3D<Precision> const &position) const = 0;
0412 
0413   /**
0414    * Like similar function in VUnplacedVolume. Here position is supposed to be
0415    * in the frame of the placed volume.
0416    */
0417   virtual Real_v SafetyToOutVec(Vector3D<Real_v> const &position) const = 0;
0418 
0419   /// to be deprecated
0420   virtual void SafetyToOut(SOA3D<Precision> const &position, Precision *const safeties) const = 0;
0421 
0422   template <typename T>
0423   VECGEOM_FORCE_INLINE T SafetyToOut(Vector3D<T> const &p) const
0424   {
0425     return SafetyToOutVec(p);
0426   }
0427 
0428   /// Simple forward to capacity on VUnplacedVolume
0429   virtual Precision Capacity();
0430 
0431   /// Get Extent of VUnplacedVolume, then apply transformation and recalculate
0432   VECCORE_ATT_HOST_DEVICE
0433   virtual void Extent(Vector3D<Precision> & /* min */, Vector3D<Precision> & /* max */) const;
0434 
0435   /// Get Normal of VUnplacedVolume, then apply transformation
0436   VECCORE_ATT_HOST_DEVICE
0437   virtual bool Normal(Vector3D<Precision> const & /*point*/, Vector3D<Precision> & /*normal*/) const;
0438 
0439   /// Like SurfaceArea on VUnplacedVolume
0440   virtual Precision SurfaceArea() const = 0;
0441 
0442 public:
0443 #ifdef VECGEOM_CUDA_INTERFACE
0444   virtual size_t DeviceSizeOf() const                                                                       = 0;
0445   virtual DevicePtr<cuda::VPlacedVolume> CopyToGpu(DevicePtr<cuda::LogicalVolume> const logical_volume,
0446                                                    DevicePtr<cuda::Transformation3D> const transform,
0447                                                    DevicePtr<cuda::VPlacedVolume> const gpu_ptr) const      = 0;
0448   virtual DevicePtr<cuda::VPlacedVolume> CopyToGpu(DevicePtr<cuda::LogicalVolume> const logical_volume,
0449                                                    DevicePtr<cuda::Transformation3D> const transform) const = 0;
0450   /**
0451    * Copy many instances of this class to the GPU.
0452    * \param host_volumes Host volumes to be copied. These should all be of the same type as the class that this function is called with.
0453    * \param logical_volumes GPU addresses of the logical volumes corresponding to the placed volumes.
0454    * \param transforms GPU addresses of the transformations corresponding to the placed volumes.
0455    * \param in_gpu_ptrs GPU addresses where the GPU instances of the host volumes should be placed.
0456    * \note This requires an explicit template instantiation of ConstructManyOnGpu<ThisClass_t>().
0457    * \see VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL
0458    */
0459   virtual void CopyManyToGpu(std::vector<VPlacedVolume const *> const &host_volumes,
0460                              std::vector<DevicePtr<cuda::LogicalVolume>> const &logical_volumes,
0461                              std::vector<DevicePtr<cuda::Transformation3D>> const &transforms,
0462                              std::vector<DevicePtr<cuda::VPlacedVolume>> const &in_gpu_ptrs) const = 0;
0463 
0464   template <typename Derived>
0465   DevicePtr<cuda::VPlacedVolume> CopyToGpuImpl(DevicePtr<cuda::LogicalVolume> const logical_volume,
0466                                                DevicePtr<cuda::Transformation3D> const transform,
0467                                                DevicePtr<cuda::VPlacedVolume> const in_gpu_ptr) const
0468   {
0469     DevicePtr<CudaType_t<Derived>> gpu_ptr(in_gpu_ptr);
0470     gpu_ptr.Construct(logical_volume, transform, nullptr, this->id(), this->GetCopyNo(), this->GetChildId());
0471     CudaAssertError();
0472     // Need to go via the void* because the regular c++ compilation
0473     // does not actually see the declaration for the cuda version
0474     // (and thus can not determine the inheritance).
0475     return DevicePtr<cuda::VPlacedVolume>((void *)gpu_ptr);
0476   }
0477   template <typename Derived>
0478   DevicePtr<cuda::VPlacedVolume> CopyToGpuImpl(DevicePtr<cuda::LogicalVolume> const logical_volume,
0479                                                DevicePtr<cuda::Transformation3D> const transform) const
0480   {
0481     DevicePtr<CudaType_t<Derived>> gpu_ptr;
0482     gpu_ptr.Allocate();
0483     return this->CopyToGpuImpl<Derived>(logical_volume, transform, DevicePtr<cuda::VPlacedVolume>((void *)gpu_ptr));
0484   }
0485 
0486 #endif
0487 
0488 #ifndef VECCORE_CUDA
0489   /// A conversion function creating a generic unspecialized instance of the placed volume
0490   virtual VPlacedVolume const *ConvertToUnspecialized() const = 0;
0491 #ifdef VECGEOM_ROOT
0492   /// A conversion function to a TGeoShape (when TGeo support is available)
0493   virtual TGeoShape const *ConvertToRoot() const = 0;
0494 #endif
0495 #ifdef VECGEOM_GEANT4
0496   /// A conversion function to a Geant4 G4VSolid (when G4 support is available)
0497   virtual G4VSolid const *ConvertToGeant4() const
0498   {
0499     throw std::runtime_error("ConvertToGeant4() not implemented for this shape type.");
0500   }
0501 #endif
0502 #endif // VECCORE_CUDA
0503 };
0504 } // namespace VECGEOM_IMPL_NAMESPACE
0505 } // namespace vecgeom
0506 
0507 #ifdef VECCORE_CUDA
0508 
0509 /**
0510  * Trigger template instantiations of DevicePtr<Type>::SizeOf() and DevicePtr<Type>::Construct.
0511  */
0512 #define VECGEOM_DEVICE_INST_PLACED_VOLUME(PlacedVol)                                                       \
0513   namespace cxx {                                                                                          \
0514   template size_t DevicePtr<cuda::PlacedVol>::SizeOf();                                                    \
0515   template void DevicePtr<cuda::PlacedVol>::Construct(DevicePtr<cuda::LogicalVolume> const logical_volume, \
0516                                                       DevicePtr<cuda::Transformation3D> const transform,   \
0517                                                       const unsigned int id, const int copy_no,            \
0518                                                       const int child_id) const;                           \
0519   }
0520 
0521 /**
0522  * Trigger template instantiations of DevicePtr<Type>::SizeOf() and DevicePtr<Type>::Construct.
0523  */
0524 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol, Extra)                                                  \
0525   namespace cxx {                                                                                                 \
0526   template size_t DevicePtr<cuda::PlacedVol, Extra>::SizeOf();                                                    \
0527   template void DevicePtr<cuda::PlacedVol, Extra>::Construct(DevicePtr<cuda::LogicalVolume> const logical_volume, \
0528                                                              DevicePtr<cuda::Transformation3D> const transform,   \
0529                                                              const unsigned int id, const int copy_no,            \
0530                                                              const int child_id) const;                           \
0531   template void ConstructManyOnGpu<cuda::PlacedVol, Extra>(                                                       \
0532       std::size_t nElement, DevicePtr<cuda::VPlacedVolume> const *gpu_ptrs,                                       \
0533       DevicePtr<cuda::LogicalVolume> const *logical, DevicePtr<cuda::Transformation3D> const *trafo,              \
0534       decltype(std::declval<VPlacedVolume>().id()) const *ids,                                                    \
0535       decltype(std::declval<VPlacedVolume>().GetCopyNo()) const *copyNos,                                         \
0536       decltype(std::declval<VPlacedVolume>().GetChildId()) const *childIds);                                      \
0537   }
0538 
0539 #if defined(VECGEOM_NO_SPECIALIZATION) || !defined(VECGEOM_CUDA_VOLUME_SPECIALIZATION)
0540 
0541 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT(PlacedVol, trans) \
0542   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, rotation::kGeneric>)
0543 
0544 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC(PlacedVol) \
0545   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT(PlacedVol, translation::kGeneric)
0546 
0547 #else // VECGEOM_NO_SPECIALIZATION
0548 
0549 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT(PlacedVol, trans)             \
0550   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, rotation::kGeneric>)  \
0551   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, rotation::kDiagonal>) \
0552   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, rotation::kIdentity>) \
0553   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x046>)               \
0554   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x054>)               \
0555   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x062>)               \
0556   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x076>)               \
0557   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x0a1>)               \
0558   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x0ad>)               \
0559   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x0dc>)               \
0560   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x0e3>)               \
0561   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x10a>)               \
0562   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x11b>)               \
0563   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x155>)               \
0564   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x16a>)               \
0565   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x18e>)               \
0566   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<trans, 0x1b1>)
0567 
0568 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC(PlacedVol)                  \
0569   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT(PlacedVol, translation::kGeneric) \
0570   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT(PlacedVol, translation::kIdentity)
0571 
0572 #endif // VECGEOM_NO_SPECIALIZATION
0573 
0574 #if defined(VECGEOM_NO_SPECIALIZATION) || !defined(VECGEOM_CUDA_VOLUME_SPECIALIZATION)
0575 
0576 #define VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALL_CUTOUT(PlacedVol, radii) \
0577   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<radii, Polyhedron::EPhiCutout::kGeneric>)
0578 
0579 #define VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALLSPEC(PlacedVol) \
0580   VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALL_CUTOUT(PlacedVol, Polyhedron::EInnerRadii::kGeneric)
0581 
0582 #else // VECGEOM_NO_SPECIALIZATION
0583 
0584 #define VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALL_CUTOUT(PlacedVol, radii)                   \
0585   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<radii, Polyhedron::EPhiCutout::kGeneric>) \
0586   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<radii, Polyhedron::EPhiCutout::kFalse>)   \
0587   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<radii, Polyhedron::EPhiCutout::kTrue>)    \
0588   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL(PlacedVol<radii, Polyhedron::EPhiCutout::kLarge>)
0589 
0590 #define VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALLSPEC(PlacedVol)                                 \
0591   VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALL_CUTOUT(PlacedVol, Polyhedron::EInnerRadii::kGeneric) \
0592   VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALL_CUTOUT(PlacedVol, Polyhedron::EInnerRadii::kFalse)   \
0593   VECGEOM_DEVICE_INST_PLACED_POLYHEDRON_ALL_CUTOUT(PlacedVol, Polyhedron::EInnerRadii::kTrue)
0594 
0595 #endif // VECGEOM_NO_SPECIALIZATION
0596 
0597 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol, Extra, Type)                                      \
0598   namespace cxx {                                                                                             \
0599   template size_t DevicePtr<cuda::PlacedVol, Extra, cuda::Type>::SizeOf();                                    \
0600   template void DevicePtr<cuda::PlacedVol, Extra, cuda::Type>::Construct(                                     \
0601       DevicePtr<cuda::LogicalVolume> const logical_volume, DevicePtr<cuda::Transformation3D> const transform, \
0602       const unsigned int id, const int copy_no, const int child_id) const;                                    \
0603   template void ConstructManyOnGpu<cuda::PlacedVol, Extra, cuda::Type>(                                       \
0604       std::size_t nElement, DevicePtr<cuda::VPlacedVolume> const *gpu_ptrs,                                   \
0605       DevicePtr<cuda::LogicalVolume> const *logical, DevicePtr<cuda::Transformation3D> const *trafo,          \
0606       decltype(std::declval<VPlacedVolume>().id()) const *ids,                                                \
0607       decltype(std::declval<VPlacedVolume>().GetCopyNo()) const *copyNos,                                     \
0608       decltype(std::declval<VPlacedVolume>().GetChildId()) const *childIds);                                  \
0609   }
0610 
0611 #if defined(VECGEOM_NO_SPECIALIZATION) || !defined(VECGEOM_CUDA_VOLUME_SPECIALIZATION)
0612 
0613 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_3(PlacedVol, trans, Type) \
0614   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, rotation::kGeneric, Type>)
0615 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC_3(PlacedVol, Type) \
0616   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_3(PlacedVol, translation::kGeneric, Type)
0617 
0618 #else // VECGEOM_NO_SPECIALIZATION
0619 
0620 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_3(PlacedVol, trans, Type)             \
0621   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, rotation::kGeneric, Type>)  \
0622   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, rotation::kDiagonal, Type>) \
0623   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, rotation::kIdentity, Type>) \
0624   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x046, Type>)               \
0625   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x054, Type>)               \
0626   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x062, Type>)               \
0627   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x076, Type>)               \
0628   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x0a1, Type>)               \
0629   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x0ad, Type>)               \
0630   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x0dc, Type>)               \
0631   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x0e3, Type>)               \
0632   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x10a, Type>)               \
0633   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x11b, Type>)               \
0634   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x155, Type>)               \
0635   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x16a, Type>)               \
0636   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x18e, Type>)               \
0637   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_3(PlacedVol<trans, 0x1b1, Type>)
0638 
0639 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC_3(PlacedVol, Type)                  \
0640   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_3(PlacedVol, translation::kGeneric, Type) \
0641   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_3(PlacedVol, translation::kIdentity, Type)
0642 
0643 #endif // VECGEOM_NO_SPECIALIZATION
0644 
0645 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol, trans, radii, phi)                                \
0646   namespace cxx {                                                                                             \
0647   template size_t DevicePtr<cuda::PlacedVol, trans, radii, phi>::SizeOf();                                    \
0648   template void DevicePtr<cuda::PlacedVol, trans, radii, phi>::Construct(                                     \
0649       DevicePtr<cuda::LogicalVolume> const logical_volume, DevicePtr<cuda::Transformation3D> const transform, \
0650       const unsigned int id, const int copy_no, const int child_id) const;                                    \
0651   template void ConstructManyOnGpu<cuda::PlacedVol, trans, radii, phi>(                                       \
0652       std::size_t nElement, DevicePtr<cuda::VPlacedVolume> const *gpu_ptrs,                                   \
0653       DevicePtr<cuda::LogicalVolume> const *logical, DevicePtr<cuda::Transformation3D> const *trafo,          \
0654       decltype(std::declval<VPlacedVolume>().id()) const *ids,                                                \
0655       decltype(std::declval<VPlacedVolume>().GetCopyNo()) const *copyNos,                                     \
0656       decltype(std::declval<VPlacedVolume>().GetChildId()) const *childIds);                                  \
0657   }
0658 
0659 #if defined(VECGEOM_NO_SPECIALIZATION) || !defined(VECGEOM_CUDA_VOLUME_SPECIALIZATION)
0660 
0661 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_4(PlacedVol, trans, radii, phi) \
0662   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, rotation::kGeneric, radii, phi>)
0663 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC_4(PlacedVol)                                                     \
0664   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_4(PlacedVol, translation::kGeneric, Polyhedron::EInnerRadii::kGeneric, \
0665                                               Polyhedron::EPhiCutout::kGeneric)
0666 
0667 #else
0668 
0669 // Really we should be enumerating the option
0670 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_4(PlacedVol, trans, radii, phi)             \
0671   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, rotation::kGeneric, radii, phi>)  \
0672   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, rotation::kDiagonal, radii, phi>) \
0673   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, rotation::kIdentity, radii, phi>) \
0674   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x046, radii, phi>)               \
0675   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x054, radii, phi>)               \
0676   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x062, radii, phi>)               \
0677   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x076, radii, phi>)               \
0678   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x0a1, radii, phi>)               \
0679   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x0ad, radii, phi>)               \
0680   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x0dc, radii, phi>)               \
0681   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x0e3, radii, phi>)               \
0682   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x10a, radii, phi>)               \
0683   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x11b, radii, phi>)               \
0684   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x155, radii, phi>)               \
0685   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x16a, radii, phi>)               \
0686   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x18e, radii, phi>)               \
0687   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_4(PlacedVol<trans, 0x1b1, radii, phi>)
0688 
0689 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_TRANS_4(PlacedVol, radii, phi)                \
0690   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_4(PlacedVol, translation::kGeneric, radii, phi) \
0691   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_4(PlacedVol, translation::kIdentity, radii, phi)
0692 
0693 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_RADII_4(PlacedVol, phi)                              \
0694   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_TRANS_4(PlacedVol, Polyhedron::EInnerRadii::kFalse, phi)   \
0695   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_TRANS_4(PlacedVol, Polyhedron::EInnerRadii::kGeneric, phi) \
0696   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_TRANS_4(PlacedVol, Polyhedron::EInnerRadii::kTrue, phi)
0697 
0698 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC_4(PlacedVol)                               \
0699   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_RADII_4(PlacedVol, Polyhedron::EPhiCutout::kFalse)   \
0700   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_RADII_4(PlacedVol, Polyhedron::EPhiCutout::kGeneric) \
0701   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_RADII_4(PlacedVol, Polyhedron::EPhiCutout::kTrue)    \
0702   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_RADII_4(PlacedVol, Polyhedron::EPhiCutout::kLarge)
0703 
0704 #endif
0705 
0706 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol, trans, rot)                                          \
0707   namespace cxx {                                                                                                      \
0708   template size_t DevicePtr<cuda::PlacedVol, trans, rot>::SizeOf();                                                    \
0709   template void DevicePtr<cuda::PlacedVol, trans, rot>::Construct(DevicePtr<cuda::LogicalVolume> const logical_volume, \
0710                                                                   DevicePtr<cuda::Transformation3D> const transform,   \
0711                                                                   const unsigned int id, const int copy_no,            \
0712                                                                   const int child_id) const;                           \
0713   template void ConstructManyOnGpu<cuda::PlacedVol, trans, rot>(                                                       \
0714       std::size_t nElement, DevicePtr<cuda::VPlacedVolume> const *gpu_ptrs,                                            \
0715       DevicePtr<cuda::LogicalVolume> const *logical, DevicePtr<cuda::Transformation3D> const *trafo,                   \
0716       decltype(std::declval<VPlacedVolume>().id()) const *ids,                                                         \
0717       decltype(std::declval<VPlacedVolume>().GetCopyNo()) const *copyNos,                                              \
0718       decltype(std::declval<VPlacedVolume>().GetChildId()) const *childIds);                                           \
0719   }
0720 
0721 #if defined(VECGEOM_NO_SPECIALIZATION) || !defined(VECGEOM_CUDA_VOLUME_SPECIALIZATION)
0722 
0723 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_BOOLEAN(PlacedVol, Op, trans) \
0724   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, rotation::kGeneric>)
0725 
0726 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC_BOOLEAN(PlacedVol, Op) \
0727   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_BOOLEAN(PlacedVol, Op, translation::kGeneric)
0728 
0729 #else // VECGEOM_NO_SPECIALIZATION
0730 
0731 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_BOOLEAN(PlacedVol, Op, trans)             \
0732   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, rotation::kGeneric>)  \
0733   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, rotation::kDiagonal>) \
0734   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, rotation::kIdentity>) \
0735   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x046>)               \
0736   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x054>)               \
0737   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x062>)               \
0738   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x076>)               \
0739   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x0a1>)               \
0740   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x0ad>)               \
0741   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x0dc>)               \
0742   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x0e3>)               \
0743   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x10a>)               \
0744   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x11b>)               \
0745   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x155>)               \
0746   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x16a>)               \
0747   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x18e>)               \
0748   VECGEOM_DEVICE_INST_PLACED_VOLUME_IMPL_BOOLEAN(PlacedVol<Op, trans, 0x1b1>)
0749 
0750 #define VECGEOM_DEVICE_INST_PLACED_VOLUME_ALLSPEC_BOOLEAN(PlacedVol, Op)                  \
0751   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_BOOLEAN(PlacedVol, Op, translation::kGeneric) \
0752   VECGEOM_DEVICE_INST_PLACED_VOLUME_ALL_ROT_BOOLEAN(PlacedVol, Op, translation::kIdentity)
0753 
0754 #endif // VECGEOM_NO_SPECIALIZATION
0755 
0756 #endif
0757 
0758 #endif // VECGEOM_VOLUMES_PLACEDVOLUME_H_