PeriDyno 1.0.0
Loading...
Searching...
No Matches
SurfaceParticleTracking.cu
Go to the documentation of this file.
1#include "SurfaceParticleTracking.h"
2
3#include "GLPointVisualModule.h"
4
5#include "Algorithm/CudaRand.h"
6
7namespace dyno
8{
9 IMPLEMENT_TCLASS(SurfaceParticleTracking, TDataType)
10
11 template<typename TDataType>
12 SurfaceParticleTracking<TDataType>::SurfaceParticleTracking()
13 : Node()
14 {
15 auto ps = std::make_shared<PointSet<TDataType>>();
16 this->statePointSet()->setDataPtr(ps);
17
18 auto render = std::make_shared<GLPointVisualModule>();
19 render->varPointSize()->setValue(0.25);
20 render->varBaseColor()->setValue(Color(1, 1, 0.1));
21 this->statePointSet()->connect(render->inPointSet());
22 this->graphicsPipeline()->pushModule(render);
23 }
24
25 template<typename TDataType>
26 SurfaceParticleTracking<TDataType>::~SurfaceParticleTracking()
27 {
28 mPosition.clear();
29 mMask.clear();
30
31 mPositionBuffer.clear();
32 mMaskBuffer.clear();
33
34 mMutex.clear();
35 }
36
37 template<typename TDataType>
38 bool SurfaceParticleTracking<TDataType>::validateInputs()
39 {
40 return this->importGranularMedia()->getDerivedNode() != nullptr;
41 }
42
43 template<typename TDataType>
44 void SurfaceParticleTracking<TDataType>::resetStates()
45 {
46 auto granular = this->importGranularMedia()->getDerivedNode();
47
48 Real ps = this->varSpacing()->getValue();
49
50 auto w = granular->varWidth()->getValue();
51 auto h = granular->varHeight()->getValue();
52
53 mNx = floor((w - 0.5f * ps) / ps) + 1;
54 mNy = floor((h - 0.5f * ps) / ps) + 1;
55 mNz = this->varLayer()->getValue() == 0 ? 1 : this->varLayer()->getValue();
56
57 mPosition.resize(mNx, mNy, mNz);
58
59 mMask.resize(mNx, mNy, mNz);
60 mMask.reset();
61
62 mPositionBuffer.resize(mNx, mNy, mNz);
63 mMaskBuffer.resize(mNx, mNy, mNz);
64 mMutex.resize(mNx, mNy, mNz);
65
66 generate();
67
68 updatePointSet();
69 }
70
71 //Section 6.1
72 template<typename Real>
73 __global__ void SPT_GenerateParticles(
74 DArray3D<Vector<Real, 3>> position,
75 DArray3D<bool> bExist,
76 int ci,
77 int cj,
78 int ck)
79 {
80 int i = blockDim.x * blockIdx.x + threadIdx.x;
81 int j = blockIdx.y * blockDim.y + threadIdx.y;
82 int k = blockIdx.z * blockDim.z + threadIdx.z;
83
84 int nx = position.nx();
85 int ny = position.ny();
86 int nz = position.nz();
87
88 if (i >= nx) return;
89 if (j >= ny) return;
90 if (k >= nz) return;
91
92 if (bExist(i, j, k))
93 {
94 return;
95 }
96
97 if (!(i % 2 == ci && j % 2 == cj && k % 2 == ck))
98 return;
99
100 RandNumber gen(position.index(i, j, k));
101 Real x, y, z;
102 x = gen.Generate();
103 y = gen.Generate();
104 z = gen.Generate();
105
106 position(i, j, k) = Vec3f(x, y, z);
107 bExist(i, j, k) = true;
108 }
109
110 template<typename TDataType>
111 void SurfaceParticleTracking<TDataType>::generate()
112 {
113 if (mNz == 1)
114 {
115 for (int ci = 0; ci < 2; ci++)
116 {
117 for (int cj = 0; cj < 2; cj++)
118 {
119 cuExecute3D(make_uint3(mNx, mNy, mNz),
120 SPT_GenerateParticles,
121 mPosition,
122 mMask,
123 ci,
124 cj,
125 0);
126 }
127 }
128 }
129 else
130 {
131 for (int ci = 0; ci < 2; ci++)
132 {
133 for (int ck = 0; ck < 2; ck++)
134 {
135 for (int cj = 0; cj < 2; cj++)
136 {
137 cuExecute3D(make_uint3(mNx, mNy, mNz),
138 SPT_GenerateParticles,
139 mPosition,
140 mMask,
141 ci,
142 cj,
143 ck);
144 }
145 }
146 }
147 }
148 }
149
150 template<typename Real>
151 __device__ Vector<Real, 2> d_transfer_velocity(Vector<Real, 4> vel)
152 {
153 Real u = vel.x < EPSILON ? 0.0f : vel.y / vel.x;
154 Real v = vel.x < EPSILON ? 0.0f : vel.z / vel.x;
155 return Vector<Real, 2>(u, v);
156 }
157
158 //Section 6.2
159 template<typename Real, typename Coord3D, typename Coord4D>
160 __global__ void SPT_AdvectParticles(
161 DArray3D<Coord3D> p_pos,
162 DArray2D<Coord4D> g_vel,
163 Real p_spacing,
164 Real g_spacing,
165 Real dt)
166 {
167 uint i = blockDim.x * blockIdx.x + threadIdx.x;
168 uint j = blockIdx.y * blockDim.y + threadIdx.y;
169 uint k = blockIdx.z * blockDim.z + threadIdx.z;
170
171 int p_nx = p_pos.nx();
172 int p_ny = p_pos.ny();
173 int p_nz = p_pos.nz();
174
175 if (i >= p_nx) return;
176 if (j >= p_ny) return;
177 if (k >= p_nz) return;
178
179 int g_nx = g_vel.nx();
180 int g_ny = g_vel.ny();
181
182 Real w00, w10, w01, w11;
183 int g_ix, g_iy, g_iz;
184
185 Coord3D p_ijk = p_pos(i, j, k);
186
187 Real g_fx = (i + p_ijk.x) * p_spacing / g_spacing;
188 Real g_fy = (j + p_ijk.y) * p_spacing / g_spacing;
189
190 if (g_fx < 0.0f) g_fx = 0.0f;
191 if (g_fx > g_nx - 1) g_fx = g_nx - 1.0f;
192 if (g_fy < 0.0f) g_fy = 0.0f;
193 if (g_fy > g_ny - 1) g_fy = g_ny - 1.0f;
194
195 g_ix = floor(g_fx); g_iy = floor(g_fy);
196 g_fx -= g_ix; g_fy -= g_iy;
197
198 if (g_ix == g_nx - 1) { g_ix = g_nx - 2; g_fx = 1.0f; }
199 if (g_iy == g_ny - 1) { g_iy = g_ny - 2; g_fy = 1.0f; }
200
201 w00 = (1.0f - g_fx) * (1.0f - g_fy);
202 w10 = g_fx * (1.0f - g_fy);
203 w01 = (1.0f - g_fx) * g_fy;
204 w11 = g_fx * g_fy;
205
206 g_ix++;
207 g_iy++;
208
209 Vector<Real, 2> vel_ijk = w00 * d_transfer_velocity(g_vel(g_ix, g_iy)) + w10 * d_transfer_velocity(g_vel(g_ix + 1, g_iy)) + w01 * d_transfer_velocity(g_vel(g_ix, g_iy + 1)) + w11 * d_transfer_velocity(g_vel(g_ix + 1, g_iy + 1));
210
211 p_ijk.x += vel_ijk.x * dt / p_spacing;
212 p_ijk.y += vel_ijk.y * dt / p_spacing;
213
214 p_pos(i, j, k) = p_ijk;
215 }
216
217 template<typename TDataType>
218 void SurfaceParticleTracking<TDataType>::advect()
219 {
220 auto granular = this->importGranularMedia()->getDerivedNode();
221
222 Real ps = this->varSpacing()->getValue();
223 Real gs = granular->varSpacing()->getValue();
224
225 Real dt = this->stateTimeStep()->getValue();
226
227 auto& computeGrid = granular->stateGrid()->getData();
228
229 cuExecute3D(make_uint3(mNx, mNy, mNz),
230 SPT_AdvectParticles,
231 mPosition,
232 computeGrid,
233 ps,
234 gs,
235 dt);
236 }
237
238 template<typename Coord3D>
239 __global__ void SPT_DepositPigments(
240 DArray3D<Coord3D> position,
241 DArray3D<Coord3D> positionBuffer,
242 DArray3D<bool> mask,
243 DArray3D<bool> maskBuffer,
244 DArray3D<uint> mutex)
245 {
246 uint i = blockIdx.x * blockDim.x + threadIdx.x;
247 uint j = blockIdx.y * blockDim.y + threadIdx.y;
248 uint k = blockIdx.z * blockDim.z + threadIdx.z;
249
250 int nx = position.nx();
251 int ny = position.ny();
252 int nz = position.nz();
253
254 if (i >= nx) return;
255 if (j >= ny) return;
256 if (k >= nz) return;
257
258 if (!maskBuffer(i, j, k)) return;
259
260 int ix, iy, iz;
261 Real fx, fy, fz;
262
263 int id = positionBuffer.index(i, j, k);
264 Coord3D pos = positionBuffer[id];
265
266 ix = floor(i + pos.x);
267 iy = floor(j + pos.y);
268 iz = floor(k + pos.z);
269
270 fx = i + pos.x - ix;
271 fy = j + pos.y - iy;
272 fz = k + pos.z - iz;
273
274 Coord3D p = Coord3D(fx, fy, fz);
275
276 if (ix < 0) { return; }
277 if (ix >= nx) { return; }
278 if (iy < 0) { return; }
279 if (iy >= ny) { return; }
280 if (iz < 0) { return; }
281 if (iz >= nz) { return; }
282
283 int id_new = position.index(ix, iy, iz);
284
285 while (atomicCAS(&(mutex[id_new]), 0, 1) == 0) break;
286 position[id_new] = p;
287 mask[id_new] = true;
288 atomicExch(&(mutex[id_new]), 0);
289 }
290
291 template<typename TDataType>
292 void SurfaceParticleTracking<TDataType>::deposit()
293 {
294 mPositionBuffer.assign(mPosition);
295 mMaskBuffer.assign(mMask);
296
297 mPosition.reset();
298 mMask.reset();
299
300 cuExecute3D(make_uint3(mNx, mNy, mNz),
301 SPT_DepositPigments,
302 mPosition,
303 mPositionBuffer,
304 mMask,
305 mMaskBuffer,
306 mMutex);
307 }
308
309 template<typename TDataType>
310 void SurfaceParticleTracking<TDataType>::updateStates()
311 {
312 advect();
313 deposit();
314 generate();
315
316 updatePointSet();
317 }
318
319 //Section 6.3
320 template<typename Real, typename Coord3D, typename Coord4D>
321 __global__ void SPT_UpdatePointSet(
322 DArray<Coord3D> points,
323 DArray2D<Coord4D> grid,
324 DArray3D<Coord3D> point3d,
325 Coord3D origin,
326 Real grid_spacing,
327 Real s)
328 {
329 uint i = blockIdx.x * blockDim.x + threadIdx.x;
330 uint j = blockIdx.y * blockDim.y + threadIdx.y;
331
332 uint width = point3d.nx();
333 uint height = point3d.ny();
334
335 if (i >= point3d.nx() || j >= point3d.ny()) return;
336
337 for (uint k = 0; k < point3d.nz(); k++)
338 {
339 Coord3D pos = point3d(i, j, k);
340 Real grid_fx = (i + pos.x) * s;
341 Real grid_fy = (j + pos.y) * s;
342
343 if (grid_fx < 0.0f) grid_fx = 0.0f;
344 if (grid_fx > width - 1) grid_fx = width - 1.0f;
345 if (grid_fy < 0.0f) grid_fy = 0.0f;
346 if (grid_fy > height - 1) grid_fy = height - 1.0f;
347
348 int gridx = floor(grid_fx); int gridy = floor(grid_fy);
349 Real fx = grid_fx - gridx; Real fy = grid_fy - gridy;
350
351 if (gridx == width - 1) { gridx = width - 2; fx = 1.0f; }
352 if (gridy == height - 1) { gridy = height - 2; fy = 1.0f; }
353
354 Real w00 = (1.0f - fx) * (1.0f - fy);
355 Real w10 = fx * (1.0f - fy);
356 Real w01 = (1.0f - fx) * fy;
357 Real w11 = fx * fy;
358
359 Coord4D gp00 = grid(gridx + 1, gridy + 1);
360 Coord4D gp10 = grid(gridx + 2, gridy + 1);
361 Coord4D gp01 = grid(gridx + 1, gridy + 2);
362 Coord4D gp11 = grid(gridx + 2, gridy + 2);
363
364 Coord4D gp = w00 * gp00 + w10 * gp10 + w01 * gp01 + w11 * gp11;
365
366 uint id = point3d.index(i, j, k);
367 points[id] = origin + Coord3D((pos.x + i) * s * grid_spacing, gp.x + gp.w - k * s * grid_spacing, (pos.z + j) * s * grid_spacing);
368 }
369 }
370
371 template<typename TDataType>
372 void SurfaceParticleTracking<TDataType>::updatePointSet()
373 {
374 auto pointSet = this->statePointSet()->getDataPtr();
375
376 float ps = this->varSpacing()->getValue();
377
378 auto granular = this->importGranularMedia()->getDerivedNode();
379
380 auto& computeGrid = granular->stateGrid()->getData();
381
382 auto& points = pointSet->getPoints();
383
384 auto heights = granular->stateHeightField()->getDataPtr();
385 auto origin = heights->getOrigin();
386 auto gridSpacing = heights->getGridSpacing();
387
388 uint num = mPosition.size();
389
390 points.resize(num);
391
392 cuExecute2D(make_uint2(mPosition.nx(), mPosition.ny()),
393 SPT_UpdatePointSet,
394 points,
395 computeGrid,
396 mPosition,
397 origin,
398 gridSpacing,
399 ps);
400 }
401
402 DEFINE_CLASS(SurfaceParticleTracking);
403}