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
|
// Author: Stephan Hageboeck, CERN, 2021
/** \file GeometryTest.cpp
* This test validates a given geometry on the GPU.
* - A geometry is read from a GDML file passed as argument.
* - This geometry is constructed both for CPU and GPU.
* - It is subsequently visited on the GPU, while information like volume IDs and transformations are recorded in a
* large array.
* - This array is copied to the host, and the host geometry is visited, comparing the data coming from the GPU.
*
* Which data are recorded and how they are compared is completely controlled by the struct GeometryInfo.
*/
#include "GeometryTest.h"
#include "VecGeom/base/Global.h"
#include "VecGeom/management/GeoManager.h"
#include "VecGeom/management/CudaManager.h"
#ifdef VECGEOM_GDML
#include "Frontend.h" // VecGeom/gdml/Frontend.h
#endif
#include <err.h>
using namespace vecgeom;
void visitVolumes(const VPlacedVolume *volume, GeometryInfo *geoData, std::size_t &volCounter,
const std::size_t nGeoData, unsigned int depth)
{
assert(volCounter < nGeoData);
geoData[volCounter++] = GeometryInfo{depth, *volume};
for (const VPlacedVolume *daughter : volume->GetDaughters()) {
visitVolumes(daughter, geoData, volCounter, nGeoData, depth + 1);
}
}
void compareGeometries(const cxx::VPlacedVolume *hostVolume, std::size_t &volumeCounter,
const std::vector<GeometryInfo> &deviceGeometry, unsigned int depth)
{
if (volumeCounter >= deviceGeometry.size()) {
errx(3, "No device volume corresponds to volume %zu", volumeCounter);
}
GeometryInfo host{depth, *hostVolume};
GeometryInfo const & device = deviceGeometry[volumeCounter];
if (!(host == device)) {
printf("\n** CPU:\n");
host.print();
printf("** GPU:\n");
device.print();
errx(4, "Volume #%zu (id=%d label=%s logicalId=%d) differs from GPU volume (id=%d logicalId=%d)\n", volumeCounter,
hostVolume->id(), hostVolume->GetLabel().c_str(), hostVolume->GetLogicalVolume()->id(),
device.id, device.logicalId);
}
volumeCounter++;
for (const cxx::VPlacedVolume *daughter : hostVolume->GetDaughters()) {
compareGeometries(daughter, volumeCounter, deviceGeometry, depth + 1);
}
}
int main(int argc, char **argv)
{
#ifdef VECGEOM_GDML
bool verbose = true;
bool validate = true;
double mm_unit = 0.1;
if (argc == 1) errx(ENOENT, "No input GDML file. Usage: ./GeometryTest <gdml>");
const char *filename = argv[1];
if (!filename || !vgdml::Frontend::Load(filename, validate, mm_unit, verbose))
errx(EBADF, "Cannot open file '%s'", filename);
auto &geoManager = GeoManager::Instance();
auto &cudaManager = CudaManager::Instance();
if (!geoManager.IsClosed()) errx(1, "Geometry not closed");
cudaManager.LoadGeometry(geoManager.GetWorld());
cudaManager.Synchronize();
printf("Visiting device geometry ... ");
const std::size_t numVols = geoManager.GetTotalNodeCount();
auto deviceGeometry = visitDeviceGeometry(cudaManager.world_gpu(), numVols);
printf("Comparing to host geometry ... ");
std::size_t volumeCounter = 0;
compareGeometries(geoManager.GetWorld(), volumeCounter, deviceGeometry, 0);
printf("%zu volumes. Done.\n", volumeCounter);
#endif
return EXIT_SUCCESS;
}
|