-
Notifications
You must be signed in to change notification settings - Fork 3
spline_spherical_gpu_pattern
The Storage is MemoryStorage<double, memSpace>.
MemoryStorage<double, utils::MemorySpace::DEVICE> d_x_device; ... etc. the raw pointers of storage are passed directly into Spline::Func
Spline::Func<memSpace> is the non-owning view of Spline. It holds raw pointers into device (or host) memory and is safe to copy into kernels.
// Spline.h / SplineKernels.h
template <utils::MemorySpace memorySpace>
class Spline::Func { // <- MyClassView analogue
public:
Func();
Func(const double* knotX, const double* knotY,
const double* coefB, const double* coefC, const double* coefD,
size_type nKnots, double c0,
bool isSubdivGrid, double a, double r, size_type numSubDiv);
DFTEFE_HOST_DEVICE_FUNC double eval(double xi) const; // <- key method
DFTEFE_HOST_DEVICE_FUNC double deriv(int order, double xi) const;
private:
const double *d_knotX, *d_knotY, *d_coefB, *d_coefC, *d_coefD;
size_type d_nKnots;
double d_c0;
bool d_isSubdivGrid;
double d_a, d_r;
size_type d_numSubDiv;
};
// Spline — the owning class (MyClass analogue)
class Spline {
public:
template <utils::MemorySpace memSpace>
Func<memSpace> getFunc() const; // <- view() analogue
template <utils::MemorySpace memSpace>
void evalAll(size_type n, const double* x, double* y,
deviceStream_t stream) const;
void set_points(...); // host-side spline fitting + syncToDevice
private:
std::vector<double> d_x, d_y, d_b, d_c, d_d; // host
MemoryStorage<double, DEVICE> d_x_device, d_y_device,
d_b_device, d_c_device, d_d_device; // device
};SphericalDataNumerical::Func<memSpace> is the nested view that composes a Spline::Func with quantum numbers and cutoff parameters.
// SphericalDataNumerical.h / SphericalDataNumericalKernels.h
template <utils::MemorySpace memorySpace>
class SphericalDataNumerical::Func { // <- MyClassView analogue (one level up)
public:
Func();
Func(utils::Spline::Func<memorySpace> radialSpline,
int l, int m, int mEff,
double constant, double cutoff, double smoothness,
double polarAngleTolerance, double cutoffTolerance,
double radiusTolerance);
DFTEFE_HOST_DEVICE_FUNC double getValue(const double* point,
const double* origin) const;
DFTEFE_HOST_DEVICE_FUNC void getGradientValue(const double* point,
const double* origin,
double* grad) const;
private:
utils::Spline::Func<memorySpace> d_radialSpline; // <- embedded view of Spline
int d_l, d_m, d_mEff;
double d_constant, d_cutoff, d_smoothness;
double d_polarAngleTolerance, d_cutoffTolerance, d_radiusTolerance;
};
// SphericalDataNumerical — owning class (MyClass analogue)
class SphericalDataNumerical : public SphericalData {
public:
template <utils::MemorySpace memSpace>
Func<memSpace> getFunc() const; // <- view() analogue
void getValueDevice(size_type n, const double* points,
const double* origin, double* out,
deviceStream_t stream) override;
void getGradientValueDevice(...) override;
private:
std::shared_ptr<const utils::Spline> d_spline; // <- owns the Spline
std::vector<int> d_qNumbers;
double d_cutoff, d_smoothness, d_polarAngleTolerance,
d_cutoffTolerance, d_radiusTolerance;
};The DFTEFE_CREATE_KERNEL macros define the policy: a kernel functor that takes Spline::Func<DEVICE> by value (cheap copy, safe for GPU), then calls spline.eval() inside the kernel body.
// SphericalDataNumericalDeviceKernels.cpp
DFTEFE_CREATE_KERNEL(
void,
SphericalDataNumericalValueKernel, // <- kernel name (policy)
{
// kernel body — the "operator()" analogue
for (size_type i = globalThreadId; i < numPoints;
i += nThreadsPerBlock * nThreadBlock)
{
// ... convert point to spherical ...
const double radialValue = spline.eval(r); // <- view's eval called
const double cutoffValue = smoothCutoffValue(r, cutoff, smoothness);
const double plmVal = plm(l, mEff, cos(theta));
const double qm = Qm(m, phi);
out[i] = radialValue * cutoffValue * constant * plmVal * qm;
}
},
const size_type numPoints,
const double* points,
const double* origin,
// ... cutoff, smoothness, l, m, mEff, constant ...
const utils::Spline::Func<utils::MemorySpace::DEVICE> spline, // <- View passed by value
double* out
);Similarly for SplineEvalAllKernel in SplineDeviceKernels.cpp, but it takes the raw pointer arguments directly (no embedded Func object) since it is the lower-level kernel that Spline::evalAll calls.
// Owning objects live on the host
SphericalDataNumerical sdn(qNumbers, rPoints, rValues, cutoff, smoothness, shFunc);
// Views are cheap to produce (just copy of raw pointers + scalars), safe for device
utils::Spline::Func<utils::MemorySpace::DEVICE> splineView =
d_spline->getFunc<utils::MemorySpace::DEVICE>();
SphericalDataNumerical::Func<utils::MemorySpace::DEVICE> sdnView =
sdn.getFunc<utils::MemorySpace::DEVICE>();
// Batch launch — views passed by value into the kernel
// (inside getValueDevice / getGradientValueDevice):
DFTEFE_LAUNCH_KERNEL(
SphericalDataNumericalValueKernel,
numPoints / DEVICE_BLOCK_SIZE + 1,
DEVICE_BLOCK_SIZE,
streamId,
numPoints, pointsDev, originDev,
cutoff, smoothness, polarAngleTol,
l, m, mEff, constant,
splineView, // <- non-owning, copied by value into kernel
outDev
);
// For scalar per-point evaluation (host or device), use the Func directly:
// HOST:
auto hostFunc = sdn.getFunc<utils::MemorySpace::HOST>();
double val = hostFunc.getValue(point.data(), origin.data());
// DEVICE (inside a user kernel):
// auto devFunc = sdn.getFunc<utils::MemorySpace::DEVICE>();
// DFTEFE_CREATE_KERNEL(..., { val[i] = devFunc.getValue(points+3*i, origin); }, ...);