peclet-dem
Performance-portable XPBD Discrete Element Method (Kokkos + ArborX)
Loading...
Searching...
No Matches
shapes_portable.hpp
Go to the documentation of this file.
1
9#ifndef DEM_SHAPES_PORTABLE_HPP
10#define DEM_SHAPES_PORTABLE_HPP
11
12#include <cmath>
13#include <vector>
14
15#include "dem_portable.hpp" // peclet::dem::F3
16
17namespace peclet::dem {
18
19// Surface point shell of a hollow cylinder (outer wall + inner wall if thick + top/bottom annulus
20// caps). Faithful copy of generate_cylinder_points.
21inline std::vector<F3> genCylinderShell(float radius, float height, float thickness,
22 float spacing) {
23 std::vector<F3> points;
24
25 float r_outer = radius;
26 float r_inner = radius - thickness;
27 float h = height;
28
29 // 1. Outer surface
30 float circumference = 2.0f * M_PI * r_outer;
31 int n_angular = std::ceil(circumference / spacing);
32 int n_vertical = std::ceil(h / spacing);
33
34 for (int i = 0; i < n_angular; ++i) {
35 float theta = 2.0f * M_PI * i / n_angular;
36 for (int j = 0; j <= n_vertical; ++j) {
37 float y = -0.5f * h + h * j / n_vertical;
38 float x = r_outer * std::cos(theta);
39 float z = r_outer * std::sin(theta);
40 points.push_back(F3{x, y, z});
41 }
42 }
43
44 // 2. Inner surface (if thick)
45 if (thickness > 0.0f) {
46 circumference = 2.0f * M_PI * r_inner;
47 n_angular = std::ceil(circumference / spacing);
48 for (int i = 0; i < n_angular; ++i) {
49 float theta = 2.0f * M_PI * i / n_angular;
50 for (int j = 0; j <= n_vertical; ++j) {
51 float y = -0.5f * h + h * j / n_vertical;
52 float x = r_inner * std::cos(theta);
53 float z = r_inner * std::sin(theta);
54 points.push_back(F3{x, y, z});
55 }
56 }
57 }
58
59 // 3. Caps (annulus) — top and bottom
60 float dr = spacing;
61 int n_radial = std::ceil(thickness / dr);
62 for (int i = 0; i <= n_radial; ++i) {
63 float r = r_inner + (r_outer - r_inner) * i / n_radial;
64 circumference = 2.0f * M_PI * r;
65 n_angular = std::ceil(circumference / spacing);
66 for (int j = 0; j < n_angular; ++j) {
67 float theta = 2.0f * M_PI * j / n_angular;
68 float x = r * std::cos(theta);
69 float z = r * std::sin(theta);
70 points.push_back(F3{x, 0.5f * h, z}); // top
71 points.push_back(F3{x, -0.5f * h, z}); // bottom
72 }
73 }
74
75 return points;
76}
77
78// Surface points of an axis-aligned box: each of the 6 faces sampled on a grid whose endpoints land
79// on the box edges (so the 8 corners are present). Faithful copy of generate_box_points.
80inline std::vector<F3> genBoxShell(float hx, float hy, float hz, float spacing) {
81 std::vector<F3> points;
82 auto nseg = [&](float half) {
83 int n = (int)std::ceil(2.0f * half / spacing);
84 return n < 1 ? 1 : n;
85 };
86 int nx = nseg(hx), ny = nseg(hy), nz = nseg(hz);
87 auto lin = [](float half, int i, int n) { return -half + 2.0f * half * (float)i / (float)n; };
88
89 // +/- x faces (vary y,z)
90 for (int j = 0; j <= ny; ++j)
91 for (int k = 0; k <= nz; ++k) {
92 float y = lin(hy, j, ny), z = lin(hz, k, nz);
93 points.push_back(F3{hx, y, z});
94 points.push_back(F3{-hx, y, z});
95 }
96 // +/- y faces (vary x,z)
97 for (int i = 0; i <= nx; ++i)
98 for (int k = 0; k <= nz; ++k) {
99 float x = lin(hx, i, nx), z = lin(hz, k, nz);
100 points.push_back(F3{x, hy, z});
101 points.push_back(F3{x, -hy, z});
102 }
103 // +/- z faces (vary x,y)
104 for (int i = 0; i <= nx; ++i)
105 for (int j = 0; j <= ny; ++j) {
106 float x = lin(hx, i, nx), y = lin(hy, j, ny);
107 points.push_back(F3{x, y, hz});
108 points.push_back(F3{x, y, -hz});
109 }
110 return points;
111}
112
113} // namespace peclet::dem
114
115#endif // DEM_SHAPES_PORTABLE_HPP
dem — portable POD types + math + analytic SDFs shared by the Kokkos kernel ports.
std::vector< F3 > genCylinderShell(float radius, float height, float thickness, float spacing)
std::vector< F3 > genBoxShell(float hx, float hy, float hz, float spacing)