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
|
#ifndef VECGEOM_VOLUMES_MULTIUNIONSTRUCT_H_
#define VECGEOM_VOLUMES_MULTIUNIONSTRUCT_H_
#include "VecGeom/base/Global.h"
#include "VecGeom/management/HybridManager2.h"
#include "VecGeom/navigation/HybridNavigator2.h"
#include "VecGeom/management/ABBoxManager.h"
#ifndef VECCORE_CUDA
#include <atomic>
#endif
namespace vecgeom {
inline namespace VECGEOM_IMPL_NAMESPACE {
/**
@brief Struct containing placed volume components representing a multiple union solid
@author mihaela.gheata@cern.ch
*/
struct MultiUnionStruct {
template <typename U>
using vector_t = vecgeom::Vector<U>;
using BVHStructure = HybridManager2::HybridBoxAccelerationStructure;
vector_t<VPlacedVolume const *> fVolumes; ///< Component placed volumes
BVHStructure *fNavHelper = nullptr; ///< Navigation helper using bounding boxes
Vector3D<Precision> fMinExtent; ///< Minimum extent
Vector3D<Precision> fMaxExtent; ///< Maximum extent
mutable Precision fCapacity = -1; ///< Capacity of the multiple union
mutable Precision fSurfaceArea = -1; ///< Surface area of the multiple union
#ifndef VECCORE_CUDA
mutable std::atomic<size_t> fLast; ///< Last located component for opportunistic relocation
#endif
size_t **fNeighbours = nullptr; ///< Array of lists of neigbours
size_t *fNneighbours = nullptr; ///< Number of neighbours for each component
size_t *fBuffer = nullptr; ///< Scratch space for storing neighbours
VECCORE_ATT_HOST_DEVICE
MultiUnionStruct()
{
fMinExtent.Set(kInfLength);
fMaxExtent.Set(-kInfLength);
#ifndef VECCORE_CUDA
fLast.store(0);
#endif
}
VECCORE_ATT_HOST_DEVICE
~MultiUnionStruct()
{
delete[] fNeighbours;
delete[] fNneighbours;
delete[] fBuffer;
}
VECCORE_ATT_HOST_DEVICE
void AddNode(VPlacedVolume const *volume)
{
using vecCore::math::Max;
using vecCore::math::Min;
Vector3D<Precision> amin, amax;
ABBoxManager::ComputeABBox(volume, &amin, &amax);
fMinExtent.Set(Min(fMinExtent.x(), amin.x()), Min(fMinExtent.y(), amin.y()), Min(fMinExtent.z(), amin.z()));
fMaxExtent.Set(Max(fMaxExtent.x(), amax.x()), Max(fMaxExtent.y(), amax.y()), Max(fMaxExtent.z(), amax.z()));
fVolumes.push_back(volume);
}
VECCORE_ATT_HOST_DEVICE
VECGEOM_FORCE_INLINE
bool ABBoxOverlap(Vector3D<Precision> const &amin1, Vector3D<Precision> const &amax1,
Vector3D<Precision> const &amin2, Vector3D<Precision> const &amax2)
{
// Check if two aligned boxes overlap
if ((amax1 - amin2).Min() < -kTolerance || (amax2 - amin1).Min() < -kTolerance) return false;
return true;
}
VECCORE_ATT_HOST_DEVICE
void Close()
{
// This method prepares the navigation structure
using Boxes_t = ABBoxManager::ABBoxContainer_t;
using BoxCorner_t = ABBoxManager::ABBox_s;
size_t nboxes = fVolumes.size();
BoxCorner_t *boxcorners = new BoxCorner_t[2 * nboxes];
Vector3D<Precision> amin, amax;
for (size_t i = 0; i < nboxes; ++i)
ABBoxManager::ComputeABBox(fVolumes[i], &boxcorners[2 * i], &boxcorners[2 * i + 1]);
Boxes_t boxes = &boxcorners[0];
fNavHelper = HybridManager2::Instance().BuildStructure(boxes, nboxes);
// Compute the lists of possibly overlapping neighbours
fNeighbours = new size_t *[nboxes];
fNneighbours = new size_t[nboxes];
memset(fNneighbours, 0, nboxes * sizeof(size_t));
fBuffer = new size_t[nboxes * nboxes];
for (size_t i = 0; i < nboxes; ++i) {
fNeighbours[i] = fBuffer + i * nboxes;
}
size_t newsize = 0;
for (size_t i = 0; i < nboxes - 1; ++i) {
for (size_t j = i + 1; j < nboxes; ++j) {
if (ABBoxOverlap(boxcorners[2 * i], boxcorners[2 * i + 1], boxcorners[2 * j], boxcorners[2 * j + 1])) {
fNeighbours[i][fNneighbours[i]++] = j;
fNeighbours[j][fNneighbours[j]++] = i;
newsize += 2;
}
}
}
// Compacting buffer of neighbours
size_t *buffer = new size_t[newsize];
size_t *nextloc = buffer;
for (size_t i = 0; i < nboxes; ++i) {
memcpy(nextloc, fNeighbours[i], fNneighbours[i] * sizeof(size_t));
fNeighbours[i] = nextloc;
nextloc += fNneighbours[i];
}
delete[] fBuffer;
fBuffer = buffer;
}
}; // End struct
} // namespace VECGEOM_IMPL_NAMESPACE
} // namespace vecgeom
#endif /* VECGEOM_VOLUMES_MULTIUNIONSTRUCT_H_ */
|