Back to home page

EIC code displayed by LXR

 
 

    


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

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 A collection of template helpers to automize implementation
0006 ///        of UnplacedVolume interfaces.
0007 /// \file volumes/UnplacedVolumeImplHelper.h
0008 /// \author First version created by Sandro Wenzel
0009 
0010 #ifndef VOLUMES_UNPLACEDVOLUMEIMPLHELPER_H_
0011 #define VOLUMES_UNPLACEDVOLUMEIMPLHELPER_H_
0012 
0013 #include "VecGeom/base/Global.h"
0014 #include "VecGeom/base/SOA3D.h"
0015 #include "VecGeom/volumes/UnplacedVolume.h"
0016 #include "VecGeom/management/VolumeFactory.h"
0017 
0018 #ifndef __clang__
0019 #pragma GCC diagnostic push
0020 // We ignore warnings of this type in this file.
0021 // The warning occurred due to potential overflow of memory address locations output[i]
0022 // where i is an unsigned long long in a loop. It can be safely ignored since such
0023 // memory locations do in fact not exist (~multiple petabyte in memory).
0024 #pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
0025 #endif
0026 
0027 namespace vecgeom {
0028 
0029 VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE_2t(class, CommonUnplacedVolumeImplHelper, typename, typename);
0030 
0031 inline namespace VECGEOM_IMPL_NAMESPACE {
0032 
0033 // kernels
0034 template <class Implementation, typename Real_v>
0035 VECGEOM_FORCE_INLINE
0036 static void DistanceToOutLoop(typename Implementation::UnplacedStruct_t const *shapestruct, const size_t offset,
0037                               const size_t size, SOA3D<Precision> const &points, SOA3D<Precision> const &directions,
0038                               Precision const *step_max, Precision *output)
0039 {
0040   using vecCore::FromPtr;
0041   for (decltype(points.size()) i(offset); i < size; i += vecCore::VectorSize<Real_v>()) {
0042     Vector3D<Real_v> point(FromPtr<Real_v>(points.x() + i), FromPtr<Real_v>(points.y() + i),
0043                            FromPtr<Real_v>(points.z() + i));
0044     Vector3D<Real_v> dir(FromPtr<Real_v>(directions.x() + i), FromPtr<Real_v>(directions.y() + i),
0045                          FromPtr<Real_v>(directions.z() + i));
0046     Real_v stepMax_v = FromPtr<Real_v>(&step_max[i]);
0047     Real_v result;
0048     Implementation::template DistanceToOut<Real_v>(*shapestruct, point, dir, stepMax_v, result);
0049     vecCore::Store(result, &output[i]);
0050   }
0051 }
0052 
0053 template <class Implementation, typename Real_v>
0054 VECGEOM_FORCE_INLINE
0055 static void SafetyToOutLoop(typename Implementation::UnplacedStruct_t const *shapestruct, const size_t offset,
0056                             const size_t size, SOA3D<Precision> const &points, Precision *output)
0057 {
0058   using vecCore::FromPtr;
0059   const decltype(points.size()) len(size);
0060   for (decltype(points.size()) i(offset); i < len; i += vecCore::VectorSize<Real_v>()) {
0061     Vector3D<Real_v> point(FromPtr<Real_v>(points.x() + i), FromPtr<Real_v>(points.y() + i),
0062                            FromPtr<Real_v>(points.z() + i));
0063     Real_v result(kInfLength);
0064     Implementation::template SafetyToOut<Real_v>(*shapestruct, point, result);
0065     vecCore::Store(result, &output[i]);
0066   }
0067 }
0068 
0069 /*!
0070  * A template class with the aim to automatically implement
0071  * interfaces of UnplacedVolume by connecting them to the separately
0072  * available (reusable) kernels.
0073  *
0074  * This is an application of the CRT pattern in order to reduce
0075  * repeating code.
0076  */
0077 template <class Implementation, class BaseUnplVol = VUnplacedVolume>
0078 class CommonUnplacedVolumeImplHelper : public BaseUnplVol {
0079 
0080 public:
0081   using UnplacedStruct_t = typename Implementation::UnplacedStruct_t;
0082   using UnplacedVolume_t = typename Implementation::UnplacedVolume_t;
0083 
0084   // bring in constructors
0085   using BaseUnplVol::BaseUnplVol;
0086   // bring in some members from base (to avoid name hiding)
0087   using BaseUnplVol::DistanceToIn;
0088   using BaseUnplVol::DistanceToOut;
0089   using BaseUnplVol::SafetyToIn;
0090   using BaseUnplVol::SafetyToOut;
0091 
0092   VECCORE_ATT_HOST_DEVICE
0093   VECGEOM_FORCE_INLINE
0094   virtual Precision DistanceToOut(Vector3D<Precision> const &p, Vector3D<Precision> const &d,
0095                                   Precision step_max = kInfLength) const override
0096   {
0097 #ifndef VECCORE_CUDA
0098     assert(d.IsNormalized() && " direction not normalized in call to  DistanceToOut ");
0099 #endif
0100     Precision output = kInfLength;
0101     Implementation::template DistanceToOut(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, d, step_max,
0102                                            output);
0103 
0104 // detect -inf responses which are often an indication for a real bug
0105 #ifndef VECCORE_CUDA
0106     assert(!((output < 0.) && std::isinf((Precision)output)));
0107 #endif
0108     return output;
0109   }
0110 
0111   // the extended DistanceToOut interface
0112   VECCORE_ATT_HOST_DEVICE
0113   VECGEOM_FORCE_INLINE
0114   virtual Precision DistanceToOut(Vector3D<Precision> const &p, Vector3D<Precision> const &d,
0115                                   Vector3D<Precision> &normal, bool &convex,
0116                                   Precision step_max = kInfLength) const override
0117   {
0118     (void)p;
0119     (void)d;
0120     (void)normal;
0121     (void)convex;
0122     (void)step_max;
0123     assert(false);
0124     return 0.;
0125   }
0126 
0127   VECCORE_ATT_HOST_DEVICE
0128   VECGEOM_FORCE_INLINE
0129   virtual bool Contains(Vector3D<Precision> const &p) const override
0130   {
0131     bool output(false);
0132     Implementation::Contains(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, output);
0133     return output;
0134   }
0135 
0136   VECCORE_ATT_HOST_DEVICE
0137   VECGEOM_FORCE_INLINE
0138   virtual EnumInside Inside(Vector3D<Precision> const &p) const override
0139   {
0140     Inside_t output(0);
0141     Implementation::Inside(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, output);
0142     return (EnumInside)output;
0143   }
0144 
0145   VECCORE_ATT_HOST_DEVICE
0146   virtual Precision DistanceToIn(Vector3D<Precision> const &p, Vector3D<Precision> const &d,
0147                                  const Precision step_max = kInfLength) const override
0148   {
0149 #ifndef VECCORE_CUDA
0150     assert(d.IsNormalized() && " direction not normalized in call to  DistanceToOut ");
0151 #endif
0152     Precision output(kInfLength);
0153     Implementation::DistanceToIn(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, d, step_max, output);
0154     return output;
0155   }
0156 
0157   VECCORE_ATT_HOST_DEVICE
0158   virtual Precision SafetyToOut(Vector3D<Precision> const &p) const override
0159   {
0160     Precision output(kInfLength);
0161     Implementation::SafetyToOut(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, output);
0162     return output;
0163   }
0164 
0165   VECCORE_ATT_HOST_DEVICE
0166   virtual Precision SafetyToIn(Vector3D<Precision> const &p) const override
0167   {
0168     Precision output(kInfLength);
0169     Implementation::SafetyToIn(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, output);
0170     return output;
0171   }
0172 
0173   virtual int MemorySize() const override { return sizeof(*this); }
0174 };
0175 
0176 /*! \brief Template implementation helper for the case of unplaced volumes/shapes
0177  * where the vector interface is implemented in terms of SIMD vector instructions.
0178  */
0179 template <class Implementation, class BaseUnplVol = VUnplacedVolume>
0180 class SIMDUnplacedVolumeImplHelper : public CommonUnplacedVolumeImplHelper<Implementation, BaseUnplVol> {
0181 public:
0182   using Real_v           = vecgeom::VectorBackend::Real_v;
0183   using UnplacedVolume_t = typename Implementation::UnplacedVolume_t;
0184   using Common_t         = CommonUnplacedVolumeImplHelper<Implementation, BaseUnplVol>;
0185 
0186   static constexpr bool SIMDHELPER = true; // property expressing that this helper provides true external SIMD support
0187   // bring in constructor
0188   using Common_t::Common_t;
0189 
0190   // the explicit SIMD interface
0191   VECCORE_ATT_HOST_DEVICE
0192   virtual Real_v DistanceToOutVec(Vector3D<Real_v> const &p, Vector3D<Real_v> const &d,
0193                                   Real_v const &step_max) const override
0194   {
0195     Real_v output;
0196     Implementation::template DistanceToOut<Real_v>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, d,
0197                                                    step_max, output);
0198     return output;
0199   }
0200 
0201   // the explicit SIMD interface
0202   VECCORE_ATT_HOST_DEVICE
0203   virtual Real_v DistanceToInVec(Vector3D<Real_v> const &p, Vector3D<Real_v> const &d,
0204                                  Real_v const &step_max) const override
0205   {
0206     Real_v output(kInfLength);
0207     Implementation::template DistanceToIn<Real_v>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, d,
0208                                                   step_max, output);
0209     return output;
0210   }
0211 
0212   // the explicit SIMD interface
0213   VECCORE_ATT_HOST_DEVICE
0214   virtual Real_v SafetyToOutVec(Vector3D<Real_v> const &p) const override
0215   {
0216     Real_v output(kInfLength);
0217     Implementation::template SafetyToOut<Real_v>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, output);
0218     return output;
0219   }
0220 
0221   // the explicit SIMD interface
0222   VECCORE_ATT_HOST_DEVICE
0223   virtual Real_v SafetyToInVec(Vector3D<Real_v> const &p) const override
0224   {
0225     Real_v output(kInfLength);
0226     Implementation::template SafetyToIn<Real_v>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), p, output);
0227     return output;
0228   }
0229 
0230   using UnplacedStruct_t = typename Implementation::UnplacedStruct_t;
0231   using Common_t::DistanceToOut;
0232   using Common_t::SafetyToOut;
0233 
0234   virtual void DistanceToOut(SOA3D<Precision> const &points, SOA3D<Precision> const &directions,
0235                              Precision const *const step_max, Precision *const output) const override
0236   {
0237     auto offset = points.size() - points.size() % vecCore::VectorSize<VectorBackend::Real_v>();
0238     auto &shape = ((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct();
0239     // vector loop treatment
0240     DistanceToOutLoop<Implementation, VectorBackend::Real_v>(&shape, 0, offset, points, directions, step_max, output);
0241     // tail treatment
0242     DistanceToOutLoop<Implementation, ScalarBackend::Real_v>(&shape, offset, points.size(), points, directions,
0243                                                              step_max, output);
0244   }
0245 
0246   virtual void SafetyToOut(SOA3D<Precision> const &points, Precision *const output) const override
0247   {
0248     auto offset = points.size() - points.size() % vecCore::VectorSize<VectorBackend::Real_v>();
0249     auto &shape = ((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct();
0250     // vector loop treatment
0251     SafetyToOutLoop<Implementation, VectorBackend::Real_v>(&shape, 0, offset, points, output);
0252     // tail treatment
0253     SafetyToOutLoop<Implementation, ScalarBackend::Real_v>(&shape, offset, points.size(), points, output);
0254   }
0255 };
0256 
0257 /*!
0258  * \brief Template implementation helper for the case of unplaced volumes/shapes
0259  * where the vector interface is implemented in terms of loops over scalar version.
0260  */
0261 template <class Implementation, class BaseUnplVol = VUnplacedVolume>
0262 class LoopUnplacedVolumeImplHelper : public CommonUnplacedVolumeImplHelper<Implementation, BaseUnplVol> {
0263 public:
0264   using Real_v           = vecgeom::VectorBackend::Real_v;
0265   using Real_s           = vecgeom::ScalarBackend::Real_v;
0266   using UnplacedVolume_t = typename Implementation::UnplacedVolume_t;
0267   using Common_t         = CommonUnplacedVolumeImplHelper<Implementation, BaseUnplVol>;
0268 
0269   static constexpr bool SIMDHELPER = false;
0270 
0271   // constructors
0272   using Common_t::Common_t;
0273   using Common_t::DistanceToIn;
0274   using Common_t::DistanceToOut;
0275   using Common_t::SafetyToIn;
0276   using Common_t::SafetyToOut;
0277 
0278   // the explicit SIMD interface
0279   VECCORE_ATT_HOST_DEVICE
0280   virtual Real_v DistanceToOutVec(Vector3D<Real_v> const &p, Vector3D<Real_v> const &d,
0281                                   Real_v const &step_max) const override
0282   {
0283     // implementation of a vector interface in terms of a scalar interface
0284     Real_v output(kInfLength);
0285     using vecCore::LaneAt;
0286     for (size_t i = 0; i < vecCore::VectorSize<Real_v>(); ++i) {
0287       Vector3D<Real_s> ps(LaneAt(p.x(), i), LaneAt(p.y(), i), LaneAt(p.z(), i)); // scalar vector
0288       Vector3D<Real_s> ds(LaneAt(d.x(), i), LaneAt(d.y(), i), LaneAt(d.z(), i)); // scalar direction;
0289       Real_s result;
0290       Implementation::template DistanceToOut<Real_s>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), ps, ds,
0291                                                      LaneAt(step_max, i), result);
0292       vecCore::AssignLane(output, i, result);
0293     }
0294     return output;
0295   }
0296 
0297   // the explicit SIMD interface
0298   VECCORE_ATT_HOST_DEVICE
0299   virtual Real_v DistanceToInVec(Vector3D<Real_v> const &p, Vector3D<Real_v> const &d,
0300                                  Real_v const &step_max) const override
0301   {
0302     // implementation of a vector interface in terms of a scalar interface
0303     Real_v output(kInfLength);
0304     using vecCore::LaneAt;
0305     for (size_t i = 0; i < vecCore::VectorSize<Real_v>(); ++i) {
0306       Vector3D<Real_s> ps(LaneAt(p.x(), i), LaneAt(p.y(), i), LaneAt(p.z(), i)); // scalar vector
0307       Vector3D<Real_s> ds(LaneAt(d.x(), i), LaneAt(d.y(), i), LaneAt(d.z(), i)); // scalar direction;
0308       Real_s tmp(-1.);
0309       Implementation::template DistanceToIn<Real_s>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), ps, ds,
0310                                                     LaneAt(step_max, i), tmp);
0311       vecCore::AssignLane(output, i, tmp);
0312     }
0313     return output;
0314   }
0315 
0316   // the explicit SIMD interface
0317   VECCORE_ATT_HOST_DEVICE
0318   virtual Real_v SafetyToOutVec(Vector3D<Real_v> const &p) const override
0319   {
0320     // implementation of a vector interface in terms of a scalar interface
0321     Real_v output(-1.);
0322     using vecCore::LaneAt;
0323     for (size_t i = 0; i < vecCore::VectorSize<Real_v>(); ++i) {
0324       Vector3D<Real_s> ps(LaneAt(p.x(), i), LaneAt(p.y(), i), LaneAt(p.z(), i)); // scalar vector
0325       Real_s tmp(kInfLength);
0326       Implementation::template SafetyToOut<Real_s>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), ps, tmp);
0327       vecCore::AssignLane(output, i, tmp);
0328     }
0329     return output;
0330   }
0331 
0332   // the explicit SIMD interface
0333   VECCORE_ATT_HOST_DEVICE
0334   virtual Real_v SafetyToInVec(Vector3D<Real_v> const &p) const override
0335   {
0336     // implementation of a vector interface in terms of a scalar interface
0337     Real_v output(kInfLength);
0338     using vecCore::LaneAt;
0339     for (size_t i = 0; i < vecCore::VectorSize<Real_v>(); ++i) {
0340       Vector3D<Real_s> ps(LaneAt(p.x(), i), LaneAt(p.y(), i), LaneAt(p.z(), i)); // scalar vector
0341       Real_s tmp;
0342       Implementation::template SafetyToIn<Real_s>(((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct(), ps, tmp);
0343       vecCore::AssignLane(output, i, tmp);
0344     }
0345     return output;
0346   }
0347 
0348   using UnplacedStruct_t = typename Implementation::UnplacedStruct_t;
0349 
0350   virtual void DistanceToOut(SOA3D<Precision> const &points, SOA3D<Precision> const &directions,
0351                              Precision const *const step_max, Precision *const output) const override
0352   {
0353     auto &shape = ((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct();
0354     DistanceToOutLoop<Implementation, Precision>(&shape, 0, points.size(), points, directions, step_max, output);
0355   }
0356 
0357   virtual void SafetyToOut(SOA3D<Precision> const &points, Precision *const output) const override
0358   {
0359     auto &shape = ((UnplacedVolume_t *)this)->UnplacedVolume_t::GetStruct();
0360     SafetyToOutLoop<Implementation, Precision>(&shape, 0, points.size(), points, output);
0361   }
0362 };
0363 } // namespace VECGEOM_IMPL_NAMESPACE
0364 } // namespace vecgeom
0365 
0366 #ifndef __clang__
0367 #pragma GCC diagnostic pop
0368 #endif
0369 
0370 #endif /* VOLUMES_UnplacedVolumeImplHelper_H_ */