1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
//@author: initial implementation Sandro Wenzel (July 2018)
#ifndef VOLUMES_SUNPLACEDVOLUME_IMPLAS_H_
#define VOLUMES_SUNPLACEDVOLUME_IMPLAS_H_
#include "VecGeom/base/Global.h"
#include "VecGeom/volumes/UnplacedVolume.h"
#include "VecGeom/management/VolumeFactory.h"
#include "VecGeom/volumes/PlacedVolImplHelper.h"
#include "VecGeom/volumes/SpecializedPlacedVolImplHelper.h"
#include "VecGeom/volumes/kernel/ImplAsImplementation.h"
#include <cassert>
#include <type_traits>
namespace vecgeom {
VECGEOM_DEVICE_DECLARE_CONV_TEMPLATE_2t(class, SUnplacedImplAs, typename, typename);
inline namespace VECGEOM_IMPL_NAMESPACE {
// A wrapper class which generically implements a specialization of UnplacedBase
// implemented in terms of another **existing** implementing volume ImplementingUnplaced.
template <typename UnplacedBase, typename ImplementingUnplaced>
class SUnplacedImplAs : public UnplacedBase {
// static assert(make sure UnplacedBase is an UnplacedVolume
public:
using UnplacedStruct_t = typename ImplementingUnplaced::UnplacedStruct_t;
template <typename... Args>
SUnplacedImplAs(Args... args) : UnplacedBase(args...)
{
fImplPtr = new ImplementingUnplaced(args...);
}
// implement the important unplaced volume interfaces
VECCORE_ATT_HOST_DEVICE
bool Contains(Vector3D<Precision> const &p) const override { return fImplPtr->ImplementingUnplaced::Contains(p); }
VECCORE_ATT_HOST_DEVICE
EnumInside Inside(Vector3D<Precision> const &p) const override { return fImplPtr->ImplementingUnplaced::Inside(p); }
// DistanceToOut
VECCORE_ATT_HOST_DEVICE
Precision DistanceToOut(Vector3D<Precision> const &p, Vector3D<Precision> const &d,
Precision step_max = kInfLength) const override
{
return fImplPtr->ImplementingUnplaced::DistanceToOut(p, d, step_max);
}
VECCORE_ATT_HOST_DEVICE
Precision DistanceToOut(Vector3D<Precision> const &p, Vector3D<Precision> const &d, Vector3D<Precision> &normal,
bool &convex, Precision step_max = kInfLength) const override
{
return fImplPtr->ImplementingUnplaced::DistanceToOut(p, d, normal, convex, step_max);
}
VECCORE_ATT_HOST_DEVICE
Real_v DistanceToOutVec(Vector3D<Real_v> const &p, Vector3D<Real_v> const &d, Real_v const &step_max) const override
{
return fImplPtr->ImplementingUnplaced::DistanceToOutVec(p, d, step_max);
}
// the container/basket interface (possibly to be deprecated)
void DistanceToOut(SOA3D<Precision> const &points, SOA3D<Precision> const &directions,
Precision const *const step_max, Precision *const output) const override
{
return fImplPtr->ImplementingUnplaced::DistanceToOut(points, directions, step_max, output);
}
// SafetyToOut
VECCORE_ATT_HOST_DEVICE
Precision SafetyToOut(Vector3D<Precision> const &p) const override
{
return fImplPtr->ImplementingUnplaced::SafetyToOut(p);
}
VECCORE_ATT_HOST_DEVICE
Real_v SafetyToOutVec(Vector3D<Real_v> const &p) const override
{
return fImplPtr->ImplementingUnplaced::SafetyToOutVec(p);
}
void SafetyToOut(SOA3D<Precision> const &points, Precision *const output) const override
{
return fImplPtr->ImplementingUnplaced::SafetyToOut(points, output);
}
// NOTE: This does not work yet (for whatever reason) since the trampoline dispatch is confused
// in UnplacedVolume.h
// DistanceToIn
// VECCORE_ATT_HOST_DEVICE
// Precision DistanceToIn(Vector3D<Precision> const &position, Vector3D<Precision> const &direction,
// const Precision step_max) const override
// {
// return fImplPtr->ImplementingUnplaced::DistanceToIn(position, direction, step_max);
// }
// VECCORE_ATT_HOST_DEVICE
// Real_v DistanceToInVec(Vector3D<Real_v> const &position, Vector3D<Real_v> const &direction,
// const Real_v &step_max) const override
// {
// return fImplPtr->ImplementingUnplaced::DistanceToInVec(position, direction, step_max);
// }
VECCORE_ATT_HOST_DEVICE
Precision SafetyToIn(Vector3D<Precision> const &position) const override
{
return fImplPtr->ImplementingUnplaced::SafetyToIn(position);
}
VECCORE_ATT_HOST_DEVICE
Real_v SafetyToInVec(Vector3D<Real_v> const &p) const override
{
return fImplPtr->ImplementingUnplaced::SafetyToInVec(p);
}
// ---------------- SamplePointOnSurface ----------------------------------------------------------
Vector3D<Precision> SamplePointOnSurface() const override
{
return fImplPtr->ImplementingUnplaced::SamplePointOnSurface();
}
// ----------------- Extent --------------------------------------------------------------------
VECCORE_ATT_HOST_DEVICE
void Extent(Vector3D<Precision> &aMin, Vector3D<Precision> &aMax) const override
{
fImplPtr->ImplementingUnplaced::Extent(aMin, aMax);
}
using StructType = decltype(std::declval<ImplementingUnplaced>().GetStruct());
VECCORE_ATT_HOST_DEVICE
StructType GetStruct() const { return fImplPtr->ImplementingUnplaced::GetStruct(); }
private:
// select target specialization helpers with SFINAE
template <typename IUnplaced, typename ImplementingKernel>
VPlacedVolume *changeTypeKeepTransformation(
VPlacedVolume const *p, typename std::enable_if<IUnplaced::SIMDHELPER, IUnplaced>::type * = nullptr) const
{
// if the implementing helper supports SIMD
auto c = VolumeFactory::ChangeTypeKeepTransformation<SIMDSpecializedVolImplHelper, ImplementingKernel>(p);
return c;
}
template <typename IUnplaced, typename ImplementingKernel>
VPlacedVolume *changeTypeKeepTransformation(
VPlacedVolume const *p, typename std::enable_if<!IUnplaced::SIMDHELPER, IUnplaced>::type * = nullptr) const
{
// if the implementing helper does not support SIMD
auto c = VolumeFactory::ChangeTypeKeepTransformation<LoopSpecializedVolImplHelper, ImplementingKernel>(p);
return c;
}
VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume, Transformation3D const *const transformation,
const TranslationCode trans_code, const RotationCode rot_code,
VPlacedVolume *const placement = NULL) const override
{
auto p = fImplPtr->ImplementingUnplaced::SpecializedVolume(volume, transformation, trans_code, rot_code, placement);
using ImplementingKernel = IndirectImplementation<SUnplacedImplAs<UnplacedBase, ImplementingUnplaced>,
typename ImplementingUnplaced::Kernel>;
// the right function to use will be selected with SFINAE and enable_if
return changeTypeKeepTransformation<ImplementingUnplaced, ImplementingKernel>(p);
// TODO: original p is no longer needed in principle: delete and deregister from GeoManager
// delete p;
}
ImplementingUnplaced *fImplPtr;
};
} // namespace VECGEOM_IMPL_NAMESPACE
} // namespace vecgeom
#endif /* VOLUMES_SUNPLACEDVOLUME_IMPLAS_H_ */
|