24#ifndef PECLET_CORE_GEOM_DEVICE_SCENE_HPP
25#define PECLET_CORE_GEOM_DEVICE_SCENE_HPP
27#include <Kokkos_Core.hpp>
37template <
class Real,
class MemSpace =
typename Kokkos::DefaultExecutionSpace::memory_space>
61 s.
nodes = nodes_.data();
62 s.
nodeCount =
static_cast<int>(nodes_.extent(0));
63 s.
grids = grids_.data();
64 s.
gridCount =
static_cast<int>(grids_.extent(0));
66 s.
sampleCount =
static_cast<long>(samples_.extent(0));
76 throw std::invalid_argument(
"DeviceScene: empty node table");
77 nodes_ = Kokkos::View<ShapeNode<Real>*,
MemSpace>(
"sceneNodes", nodes.size());
79 Kokkos::View<Instance<Real>*,
MemSpace>(
"sceneInsts",
insts.empty() ? 1 :
insts.size());
81 Kokkos::View<GridDesc<Real>*,
MemSpace>(
"sceneGrids", grids.empty() ? 1 : grids.size());
82 samples_ = Kokkos::View<float*, MemSpace>(
"scenePool",
pool.empty() ? 1 :
pool.size());
84 auto h = Kokkos::create_mirror_view(
view);
85 for (std::size_t
i = 0;
i <
host.size(); ++
i)
87 Kokkos::deep_copy(
view, h);
97 Kokkos::View<ShapeNode<Real>*,
MemSpace> nodes_;
98 Kokkos::View<Instance<Real>*,
MemSpace> insts_;
99 Kokkos::View<GridDesc<Real>*,
MemSpace> grids_;
100 Kokkos::View<float*, MemSpace> samples_;
101 bool instCount0_ =
false;
104 bool empty()
const {
return nodes_.extent(0) == 0; }
105 int instanceCount()
const {
return instCount0_ ? 0 :
static_cast<int>(insts_.extent(0)); }
114template <
class ExecSpace,
class Real,
class PtsView,
class OutView>
118 const std::size_t n =
pts.extent(0);
119 Kokkos::parallel_for(
120 "peclet::core::geom::evalSphereUnionPoints", Kokkos::RangePolicy<ExecSpace>(
space, 0, n),
133 for (std::size_t
i = 0;
i < n; ++
i)
139template <
class ExecSpace,
class Real,
class PtsView,
class OutView>
142 const std::size_t n =
pts.extent(0);
143 Kokkos::parallel_for(
144 "peclet::core::geom::evalScenePoints", Kokkos::RangePolicy<ExecSpace>(
space, 0, n),
152 for (std::size_t
i = 0;
i < n; ++
i)
164template <
class Real,
class MemSpace =
typename Kokkos::DefaultExecutionSpace::memory_space>
179 std::vector<Real> cx, cy, cz, r;
181 d.uploadUnion(cx, cy, cz, r);
188 hu.n =
static_cast<int>(cx.size());
189 hu.equalR =
d.uMeta_.equalR;
196 const long nb = 32L * 32L * 32L;
197 if ((
long)
hostView.instanceCount *
nb <= 50L * 1000L * 1000L)
214 v.
scene = scene_.view();
218 v.
grid.offsets = gOff_.data();
219 v.
grid.items = gItems_.data();
220 v.
grid.always = gAlways_.data();
230 void uploadUnion(
const std::vector<Real>& cx,
const std::vector<Real>& cy,
231 const std::vector<Real>& cz,
const std::vector<Real>& r) {
232 auto up = [](
const char*
nm,
const std::vector<Real>& h) {
233 Kokkos::View<Real*, MemSpace> v(
nm, h.size());
234 auto m = Kokkos::create_mirror_view(v);
235 for (std::size_t
i = 0;
i < h.size(); ++
i)
237 Kokkos::deep_copy(v,
m);
240 cx_ =
up(
"sq_cx", cx);
241 cy_ =
up(
"sq_cy", cy);
242 cz_ =
up(
"sq_cz", cz);
244 uMeta_.n =
static_cast<int>(cx.size());
245 uMeta_.equalR =
true;
246 for (std::size_t
i = 1;
i < r.size(); ++
i)
248 uMeta_.equalR =
false;
249 uMeta_.r0 = r.empty() ?
Real(0) : r[0];
253 gMeta_.alwaysCount =
static_cast<int>(g.always.size());
254 auto up = [](
const char*
nm,
const std::vector<int>& h) {
255 Kokkos::View<int*, MemSpace> v(
nm, h.empty() ? 1 : h.size());
256 auto m = Kokkos::create_mirror_view(v);
257 for (std::size_t
i = 0;
i < h.size(); ++
i)
259 Kokkos::deep_copy(v,
m);
262 gOff_ =
up(
"sq_off", g.offsets);
263 gItems_ =
up(
"sq_items", g.items);
264 gAlways_ =
up(
"sq_always", g.always);
268 Kokkos::View<Real*, MemSpace> cx_, cy_, cz_, r_;
269 Kokkos::View<int*, MemSpace> gOff_, gItems_, gAlways_;
277template <
class ExecSpace,
class Real,
class PtsView,
class OutView>
280 const std::size_t n =
pts.extent(0);
281 Kokkos::parallel_for(
282 "peclet::core::geom::evalQueryPoints", Kokkos::RangePolicy<ExecSpace>(
space, 0, n),
Owning device-resident scene. Copyable (Views are shared_ptr-like); view() is cheap.
static DeviceScene fromFlat(const std::vector< int > &nodeInts, const std::vector< Real > &nodeReals, const std::vector< int > &instInts, const std::vector< Real > &instReals)
Upload from the flat encoding (the binding path; see scene_builder.hpp for the layout).
int instanceCount() const
SceneView< Real > view() const
Non-owning bundle over the device arrays; capture by value into kernels.
static DeviceScene from(const SceneBuilder< Real > &b)
Upload from a host SceneBuilder (the composition path).
const std::vector< ShapeNode< Real > > & nodes() const
const std::vector< Instance< Real > > & instances() const
SceneView< Real > view() const
Non-owning view over this builder's arrays. Invalidated by any further add*.
const std::vector< float > & samples() const
const std::vector< GridDesc< Real > > & grids() const
static SceneBuilder decode(const std::vector< int > &nodeInts, const std::vector< Real > &nodeReals, const std::vector< int > &instInts, const std::vector< Real > &instReals, const std::vector< GridDesc< Real > > &grids, const std::vector< float > &pool)
Rebuild from the flat encoding (grids and the sample pool are carried across verbatim).
Owns everything a SceneQueryView needs on ONE memory space: the DeviceScene, the extracted sphere-uni...
SceneQueryDevice()=default
const DeviceScene< Real, MemSpace > & scene() const
static SceneQueryDevice build(const SceneBuilder< Real > &b, Vec3< Real > origin, Vec3< Real > extent, PeriodicBox< Real > box, bool accelerate=true, int nbHint=0)
Build from a host SceneBuilder.
SceneQueryView< Real > view() const
POD view for kernels; valid while this object lives.
PECLET_HD Real evalSphereUnionGrid(const SphereUnionView< Real > &u, Vec3< Real > p, const PeriodicBox< Real > &box, const CandidateGridView< Real > &g)
Union SDF through the candidate grid: bin lookup + short list, full-scan fallback when the bin is out...
CandidateGrid< Real > buildSceneCandidateGrid(const SceneView< Real > &sc, Vec3< Real > origin, Vec3< Real > extent, const PeriodicBox< Real > &box, Real binSizeHint=0)
Candidate grid for a GENERAL scene: certified instances splat Lipschitz bounds evaluated at bin cente...
void evalSphereUnionPoints(const ExecSpace &space, const SphereUnionView< Real > &u, const PeriodicBox< Real > &box, const CandidateGridView< Real > &grid, const PtsView &pts, const OutView &out)
Batched sphere-union evaluation, device: pts is (N,3), out is (N), any layouts/memory spaces reachabl...
void evalScenePointsHost(const SceneView< Real > &sc, const Real *pts, std::size_t n, Real *out)
bool extractSphereUnion(const SceneView< Real > &sc, std::vector< Real > &cx, std::vector< Real > &cy, std::vector< Real > &cz, std::vector< Real > &r)
Try to view a scene as a PLAIN sphere union: every instance a single kSphere leaf with a bitwise-iden...
PECLET_HD Real evalScene(const SceneView< Real > &sc, Vec3< Real > p)
Convenience: the union of EVERY instance.
void evalQueryPoints(const ExecSpace &space, const SceneQueryView< Real > &q, const PtsView &pts, const OutView &out)
Batched driver over a SceneQueryView (the form the restructured AMR builders and flow's sampling kern...
void evalScenePoints(const ExecSpace &space, const SceneView< Real > &sc, const PtsView &pts, const OutView &out)
Batched general-scene evaluation (union over instances), device.
CandidateGrid< Real > buildSphereCandidateGrid(const SphereUnionView< Real > &u, Vec3< Real > origin, Vec3< Real > extent, const PeriodicBox< Real > &box, int nbHint=0)
Geometry-driven candidate build for a sphere union over [origin, origin+extent).
void evalSphereUnionPointsHost(const SphereUnionView< Real > &u, const PeriodicBox< Real > &box, const CandidateGridView< Real > &grid, const Real *pts, std::size_t n, Real *out)
Host-pointer form (the oracle / today's single-threaded builders): plain loop, no Kokkos types in the...
ExecSpace::memory_space MemSpace
Kokkos::View< T *, MemSpace > View
1D device array.
Kokkos::DefaultExecutionSpace ExecSpace
double Real
Default host floating type. Device kernels may use float; conversions happen at the boundary.
SphereUnionView< Real > u
CandidateGridView< Real > grid
const Instance< Real > * instances
const GridDesc< Real > * grids
const ShapeNode< Real > * nodes