PeriDyno 1.0.0
Loading...
Searching...
No Matches
SemiAnalyticalParticleShifting.cu
Go to the documentation of this file.
1#include "SemiAnalyticalParticleShifting.h"
2
3#include "SemiAnalyticalSummationDensity.h"
4
5#include "IntersectionArea.h"
6
7namespace dyno {
8
9 IMPLEMENT_TCLASS(SemiAnalyticalParticleShifting, TDataType)
10
11 template<typename TDataType>
12 SemiAnalyticalParticleShifting<TDataType>::SemiAnalyticalParticleShifting()
13 : ParticleApproximation<TDataType>()
14 {
15 this->varInertia()->setValue(Real(0.1));
16 this->varBulk()->setValue(Real(0.5));
17
18 mCalculateDensity = std::make_shared<SemiAnalyticalSummationDensity<TDataType>>();
19 this->inSamplingDistance()->connect(mCalculateDensity->inSamplingDistance());
20 this->inSmoothingLength()->connect(mCalculateDensity->inSmoothingLength());
21 this->inPosition()->connect(mCalculateDensity->inPosition());
22 this->inNeighborIds()->connect(mCalculateDensity->inNeighborIds());
23 this->inNeighborTriIds()->connect(mCalculateDensity->inNeighborTriIds());
24 this->inTriangleSet()->connect(mCalculateDensity->inTriangleSet());
25 this->varRestDensity()->connect(mCalculateDensity->varRestDensity());
26 };
27
28 template<typename TDataType>
29 SemiAnalyticalParticleShifting<TDataType>::~SemiAnalyticalParticleShifting()
30 {
31 mLambda.clear();
32 mDeltaPos.clear();
33 mPosBuf.clear();
34 };
35
36 __device__ inline Real KernSpikyGradient(const Real r, const Real h)
37 {
38 const Real q = r / h;
39 if (q > 1.0f) return 0.0;
40 else {
41 const Real d = 1.0 - q;
42 const Real hh = h * h;
43 return -45.0f / ((Real)M_PI * hh*h) *d*d;
44 }
45 }
46
47 template<typename Real>
48 __device__ inline Real KernSpiky(const Real r, const Real h)
49 {
50 const Real q = r / h;
51 if (q > 1.0f) return 0.0;
52 else {
53 const Real d = 1.0 - q;
54 const Real hh = h * h;
55 return -15.0f / ((Real)M_PI * hh*h) *d*d*d;
56 }
57 }
58
59 template<typename Real>
60 __device__ inline Real kernWeight1(const Real r, const Real h)
61 {
62 const Real q = r / h;
63 if (q > 1.0f) return 0.0f;
64 else {
65 const Real d = 1.0f - q;
66 const Real hh = h * h;
67 return (1.0 - q * q*q*q)*h*h;
68 }
69 }
70
71
72 template<typename Real>
73 __device__ inline Real kernWRR1(const Real r, const Real h)
74 {
75 Real w = kernWeight1(r, h);
76 const Real q = r / h;
77 if (q < 0.5f)
78 {
79 return w / (0.25f*h*h);
80 }
81 return w / r / r;
82 }
83
84 template <typename Real, typename Coord>
85 __global__ void SAPS_ComputeBoundaryGradient(
86 DArray<Coord> adhesion,
87 DArray<Real> totalW,
88 DArray<Coord> dir,
89 DArray<Coord> position,
90 DArrayList<int> neighbors,
91 DArrayList<int> neighborTri,
92 DArray<Triangle> m_triangle_index,
93 DArray<Coord> positionTri,
94 Real smoothingLength)
95 {
96 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
97 if (pId >= position.size()) return;
98
99 Coord pos_i = position[pId];
100 Coord Tri_direction(0);
101 Coord numerator(0);
102
103 List<int>& nbrIds_i = neighbors[pId];
104 int nbSize = nbrIds_i.size();
105
106 List<int>& nbrTriIds_i = neighborTri[pId];
107 int nbSizeTri = nbrTriIds_i.size();
108
109 Real AreaB;
110 for (int ne = 0; ne < nbSizeTri; ne++)
111 {
112 int j = nbrTriIds_i[ne];
113
114 Triangle3D t3d(positionTri[m_triangle_index[j][0]], positionTri[m_triangle_index[j][1]], positionTri[m_triangle_index[j][2]]);
115 Plane3D PL(positionTri[m_triangle_index[j][0]], t3d.normal());//plane of Tri
116 Point3D p3d(pos_i);
117
118 Point3D nearest_pt = p3d.project(PL);
119 Real r = (nearest_pt.origin - pos_i).norm();//distance between Fluid point and plane
120 float d = p3d.distance(PL);
121
122 Real AreaSum = calculateIntersectionArea(p3d, t3d, smoothingLength);
123 Real MinDistance = abs(p3d.distance(t3d));
124 Coord Min_Pt = (p3d.project(t3d)).origin - pos_i;
125
126
127 Tri_direction += t3d.normal()*KernSpiky(MinDistance, smoothingLength);
128
129 Coord boundNorm = t3d.normal();
130
131 if (Min_Pt.norm() > 0)
132 if (ne < nbSizeTri - 1)
133 {
134 int jn;
135 do
136 {
137 jn = nbrTriIds_i[ne + 1];
138
139 Triangle3D t3d_n(positionTri[m_triangle_index[jn][0]], positionTri[m_triangle_index[jn][1]], positionTri[m_triangle_index[jn][2]]);
140 if ((t3d.normal().cross(t3d_n.normal())).norm() > EPSILON)// not at the same plane
141 {
142 break;
143 }
144
145 Real minDis = abs(p3d.distance(t3d_n));
146 Coord minPt = (p3d.project(t3d_n)).origin - pos_i;
147
148 AreaSum += calculateIntersectionArea(p3d, t3d_n, smoothingLength);
149
150 if (abs(p3d.distance(t3d_n)) < MinDistance)
151 {
152 MinDistance = minDis;
153 Min_Pt = minPt;
154
155 Tri_direction += t3d_n.normal() * KernSpiky(MinDistance, smoothingLength);
156 }
157
158
159 ne++;
160 } while (ne < nbSizeTri - 1);
161 }
162
163 Min_Pt /= Min_Pt.norm();
164
165
166 d = abs(d);
167 if (smoothingLength - d > EPSILON&& smoothingLength* smoothingLength - d * d > EPSILON&& d > EPSILON)
168 {
169 Coord n_PL = -t3d.normal();
170 n_PL = n_PL / n_PL.norm();
171
172 AreaB = M_PI * (smoothingLength * smoothingLength - d * d);//A0
173
174 Real ep = 0.0001;
175 Real weightS = ep*KernSpiky(r, smoothingLength);
176 Real weightS_hat = ep* r*r*r* KernSpikyGradient(r, smoothingLength);
177
178
179 Real EP_ij = - weightS * AreaSum;
180 Real totalWeight = weightS_hat
181 * 2.0 * (M_PI) * (1 - d / smoothingLength)//Omega_0
182 * AreaSum * n_PL.dot(Min_Pt)//£¨n_s¡¤d_n£©*As
183 / AreaB;//A0
184
185 numerator += EP_ij * boundNorm;
186 totalW[pId] += totalWeight;//denominator
187
188 }
189 }
190
191 if (Tri_direction.norm() > EPSILON) {
192 Tri_direction /= Tri_direction.norm();
193 }
194 else Tri_direction = Coord(0);
195
196 dir[pId] = Tri_direction;
197 adhesion[pId] = numerator;
198 }
199
200 template <typename Real, typename Coord>
201 __global__ void PR_ComputeGradient(
202 DArray<Coord> grads,//delta Pos
203 DArray<Coord> Adhesion,
204 DArray<Real> totalW,//total weight from boundary mesh
205 DArray<Real> rhoArr,//rDensity
206 DArray<Coord> curPos,
207 DArray<Coord> originPos,
208 DArrayList<int> neighbors,
209 Real mass,
210 Real h,
211 Real inertia,
212 Real bulk,
213 Real surfaceTension,
214 Real adhesion)
215 {
216 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
217 if (pId >= curPos.size()) return;
218
219 Real a1 = inertia;
220 Real a2 = bulk;
221 Real a3 = surfaceTension;
222 Real a4 = adhesion;
223
224 Real w1 = 1.0f*a1;
225 Real w2 = 0.005f*(rhoArr[pId] - 1000.0f) / (1000.0f)*a2;
226 if (w2 < EPSILON)
227 {
228 w2 = 0.0f;
229 }
230 Real w3 = 0.005f*a3;
231 Real w4 = a4;
232
233 Coord pos_i = curPos[pId];
234
235 Coord grad1_i = originPos[pId] - pos_i;
236
237 Coord grad2(0);
238 Real total_weight2 = 0.0f;
239 Coord grad3(0);
240 Real total_weight3 = 0.0f;
241
242 List<int>& list_i = neighbors[pId];
243 int nbSize = list_i.size();
244
245 for (int ne = 0; ne < nbSize; ne++)
246 {
247 int j = list_i[ne];
248 Coord pos_j = curPos[j];
249 Real r = (pos_i - pos_j).norm();
250
251 if (r > EPSILON)
252 {
253 Real weight2 = -mass * KernSpikyGradient(r, h);
254 total_weight2 += weight2;
255 Coord g2_ij = weight2 * (pos_i - pos_j) * (1.0f / r);
256 grad2 += g2_ij;
257
258 Real weight3 = kernWRR1(r, h);
259 total_weight3 += weight3;
260 Coord g3_ij = weight3 * (pos_i - pos_j)* (1.0f / r);
261 grad3 += g3_ij;
262 }
263 }
264 //printf("totalW: %f\n", total_weight4);
265 total_weight2 = total_weight2 < EPSILON ? 1.0f : total_weight2;
266 total_weight3 = total_weight3 < EPSILON ? 1.0f : total_weight3;
267
268 grad2 /= total_weight2;
269 grad3 /= total_weight3;
270
271
272 //bulk energy
273 for (int ne = 0; ne < nbSize; ne++)
274 {
275 int j = list_i[ne];
276 Coord pos_j = curPos[j];
277 Real r = (pos_i - pos_j).norm();
278
279 if (r > EPSILON)
280 {
281 Real weight2 = -mass * KernSpikyGradient(r, h);
282 Coord g2_ij = (weight2 / total_weight2) * (pos_i - pos_j) * (1.0f / r);
283 atomicAdd(&grads[j][0], -w2 * g2_ij[0]);
284 atomicAdd(&grads[j][1], -w2 * g2_ij[1]);
285 atomicAdd(&grads[j][2], -w2 * g2_ij[2]);
286 }
287 }
288
289 //Surface tension
290 Coord nGrad3;
291 if (grad3.norm() > EPSILON)
292 {
293 Real temp = grad3.norm();
294 nGrad3 = grad3 / temp;
295 }
296
297 Real energy = grad3.dot(grad3);
298
299 //Adhesion
300 Coord grad4(0);
301 Real total_weight4(0);
302
303 if (totalW.size() > 0)
304 total_weight4 = totalW[pId];
305
306 if (Adhesion[pId].norm() > 0 && Adhesion.size() > 0) {
307 grad4 = Adhesion[pId];
308 }
309
310 total_weight4 = total_weight4 < EPSILON ? 1.0f : total_weight4;
311 grad4 /= total_weight4;
312
313 Coord nGrad4;
314 if (grad4.norm() > 0) {
315 nGrad4 = grad4 / grad4.norm();
316 }
317
318 Real energy_solid = grad4.dot(grad4);
319 Coord shift4 = w4 * energy_solid*nGrad4;
320
321 Real max_ax = abs(shift4[0]);
322 if (abs(shift4[1]) > max_ax) max_ax = abs(shift4[1]);
323 if (abs(shift4[2]) > max_ax) max_ax = abs(shift4[2]);
324
325 Real threash = 0.00005;
326 if (max_ax > threash)
327 for (int i = 0; i < 3; ++i)
328 {
329 shift4[i] /= max_ax;
330 shift4[i] *= threash;
331 }
332
333 atomicAdd(&grads[pId][0], w1*grad1_i[0] + w2 * grad2[0] - w3 * energy*nGrad3[0] - shift4[0]);
334 atomicAdd(&grads[pId][1], w1*grad1_i[1] + w2 * grad2[1] - w3 * energy*nGrad3[1] - shift4[1]);
335 atomicAdd(&grads[pId][2], w1*grad1_i[2] + w2 * grad2[2] - w3 * energy*nGrad3[2] - shift4[2]);
336 }
337
338 template <typename Coord>
339 __global__ void SAPS_UpdatePosition(
340 DArray<Coord> grads,
341 DArray<Coord> curPos)
342 {
343 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
344 if (pId >= curPos.size()) return;
345
346 curPos[pId] += grads[pId];
347 }
348
349 template <typename Real, typename Coord>
350 __global__ void SAPS_UpdateVelocity(
351 DArray<Coord> velArr,
352 DArray<Coord> curArr,
353 DArray<Coord> originArr,
354 DArray<Coord> TriDir,//normal of boundary
355 Real dt)
356 {
357 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
358 if (pId >= velArr.size()) return;
359
360 Plane3D PL(curArr[pId], TriDir[pId]);
361 Point3D origP(originArr[pId]);
362 Point3D projectedP = origP.project(PL);
363 Coord boundary_vec = projectedP.origin - curArr[pId];
364 if (boundary_vec.norm() > 0)
365 boundary_vec /= boundary_vec.norm();
366
367 Real fr = 0.97f;//0.96f
368 boundary_vec *= fr;
369 boundary_vec[0] = 1.0f - abs(boundary_vec[0]);
370 boundary_vec[1] = 1.0f - abs(boundary_vec[1]);
371 boundary_vec[2] = 1.0f - abs(boundary_vec[2]);
372
373 velArr[pId] += (curArr[pId] - originArr[pId]) / dt;
374
375 //*********boundary friction part
376 if (boundary_vec.norm() > 0) {
377 if (abs(boundary_vec[0]) > fr)
378 velArr[pId][0] *= boundary_vec[0];
379 else
380 velArr[pId][0] *= fr;
381 if (abs(boundary_vec[1]) > fr)
382 velArr[pId][1] *= boundary_vec[1];
383 else
384 velArr[pId][1] *= fr;
385 if (abs(boundary_vec[2]) > fr)
386 velArr[pId][2] *= boundary_vec[2];
387 else
388 velArr[pId][2] *= fr;
389 }
390 }
391
392 template<typename TDataType>
393 void SemiAnalyticalParticleShifting<TDataType>::compute()
394 {
395 Real dt = this->inTimeStep()->getData();
396
397 int num = this->inPosition()->size();
398 mLambda.resize(num);
399 mDeltaPos.resize(num);
400 mPosBuf.resize(num);
401 mAdhesionEP.resize(num);
402 mTotalW.resize(num);
403 mBoundaryDir.resize(num);
404 mBoundaryDis.resize(num);
405 mAdhesionEP.reset();
406 mTotalW.reset();
407 mBoundaryDir.reset();
408 mBoundaryDis.reset();
409
410 Real d = mCalculateDensity->inSamplingDistance()->getValue();
411 Real rho_0 = mCalculateDensity->varRestDensity()->getValue();
412 Real mass = d * d*d*rho_0;
413
414 auto ts = this->inTriangleSet()->constDataPtr();
415 auto& triVertex = ts->getPoints();
416 auto& triIndex = ts->getTriangles();
417
418 mCalculateDensity->update();
419
420 mPosBuf.assign(inPosition()->getData());
421
422 int iter = 0;
423 uint maxIter = this->varInterationNumber()->getData();
424 while (iter++ < maxIter)
425 {
426 mDeltaPos.reset();
427
428 mCalculateDensity->update();
429
430 if (this->inNeighborTriIds()->getData().size() > 0) {
431 cuExecute(num,
432 SAPS_ComputeBoundaryGradient,
433 mAdhesionEP,
434 mTotalW,
435 mBoundaryDir,
436 this->inPosition()->getData(),
437 this->inNeighborIds()->getData(),
438 this->inNeighborTriIds()->getData(),
439 triIndex,
440 triVertex,
441 this->inSmoothingLength()->getData());
442 }
443
444 cuExecute(num,
445 PR_ComputeGradient,
446 mDeltaPos,
447 mAdhesionEP,
448 mTotalW,
449 mCalculateDensity->outDensity()->getData(),
450 this->inPosition()->getData(),
451 mPosBuf,
452 this->inNeighborIds()->getData(),
453 mass,
454 this->inSmoothingLength()->getData(),
455 this->varInertia()->getData(),
456 this->varBulk()->getData(),
457 this->varSurfaceTension()->getData(),
458 this->varAdhesionIntensity()->getData());
459
460 cuExecute(num,
461 SAPS_UpdatePosition,
462 mDeltaPos,
463 this->inPosition()->getData());
464 }
465
466 cuExecute(num,
467 SAPS_UpdateVelocity,
468 this->inVelocity()->getData(),
469 this->inPosition()->getData(),
470 mPosBuf,
471 mBoundaryDir,
472 dt);
473 };
474
475 DEFINE_CLASS(SemiAnalyticalParticleShifting);
476}