1#include "SemiAnalyticalPBD.h"
3#include "SemiAnalyticalSummationDensity.h"
4#include "IntersectionArea.h"
8 IMPLEMENT_TCLASS(SemiAnalyticalPBD, TDataType)
10 template <typename TDataType>
11 SemiAnalyticalPBD<TDataType>::SemiAnalyticalPBD()
14 mCalculateDensity = std::make_shared<SemiAnalyticalSummationDensity<TDataType>>();
15 this->inSmoothingLength()->connect(mCalculateDensity->inSmoothingLength());
16 this->inSamplingDistance()->connect(mCalculateDensity->inSamplingDistance());
17 this->inPosition()->connect(mCalculateDensity->inPosition());
18 this->inNeighborParticleIds()->connect(mCalculateDensity->inNeighborIds());
19 this->inNeighborTriangleIds()->connect(mCalculateDensity->inNeighborTriIds());
20 this->inTriangleSet()->connect(mCalculateDensity->inTriangleSet());
23 template <typename TDataType>
24 SemiAnalyticalPBD<TDataType>::~SemiAnalyticalPBD()
31 template <typename TDataType>
32 void SemiAnalyticalPBD<TDataType>::constrain()
34 int num = this->inPosition()->size();
36 if (mLamda.size() != num) {
38 mDeltaPos.resize(num);
39 mPosBuffer.resize(num);
42 mPosBuffer.assign(this->inPosition()->getData());
45 auto maxIter = this->varInterationNumber()->getData();
46 while (iter++ < maxIter) {
53 __device__ inline float kernGradientMeshPBD(const float r, const float h)
61 const Real d = 1.0 - q;
62 const Real hh = h * h;
63 return -45.0f / ((Real)M_PI * hh * h) * (1.0f / 3.0f * (hh * h - r * r * r) - 1.0f / 2.0f / h * (hh * hh - r * r * r * r) + 1.0f / 5.0f / hh * (hh * hh * h - r * r * r * r * r));
67 template <typename Real, typename Coord>
68 __global__ void K_ComputeLambdasMesh(
69 DArray<Real> lambdaArr,
72 DArray<TopologyModule::Triangle> Tri,
73 DArray<Coord> positionTri,
74 DArrayList<int> neighbors,
75 DArrayList<int> neighborsTri,
76 SpikyKernel<Real> kern,
78 Real samplingDistance)
80 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
81 if (pId >= posArr.size())
84 List<int>& triList_i = neighborsTri[pId];
85 int nbSizeTri = triList_i.size();
86 Real dis_n = REAL_MAX;
88 //semi-analytical boundary integration
89 Real lamda_i = Real(0);
90 Coord pos_i = posArr[pId];
92 for (int ne = 0; ne < nbSizeTri; ne++)
94 int j = triList_i[ne];
95 Triangle3D t3d(positionTri[Tri[j][0]], positionTri[Tri[j][1]], positionTri[Tri[j][2]]);
96 Plane3D PL(positionTri[Tri[j][0]], t3d.normal());
98 Point3D nearest_pt = p3d.project(PL);
99 Real r = (nearest_pt.origin - pos_i).norm();
101 Real AreaSum = calculateIntersectionArea(p3d, t3d, smoothingLength); //A_s in equation 10
102 Real MinDistance = (p3d.distance(t3d)); //d_n (scalar) in equation 10
103 Coord Min_Pt = (p3d.project(t3d)).origin - pos_i; //d_n (vector) in equation 10
104 Coord Min_Pos = p3d.project(t3d).origin;
105 if (ne < nbSizeTri - 1 && triList_i[ne + 1] < 0)
107 //triangle clustering
111 jn = triList_i[ne + 1];
113 Triangle3D t3d_n(positionTri[Tri[jn][0]], positionTri[Tri[jn][1]], positionTri[Tri[jn][2]]);
114 if ((t3d.normal().cross(t3d_n.normal())).norm() > EPSILON)
117 AreaSum += calculateIntersectionArea(p3d, t3d_n, smoothingLength);
119 if (abs(p3d.distance(t3d_n)) < abs(MinDistance))
121 MinDistance = (p3d.distance(t3d_n));
122 Min_Pt = (p3d.project(t3d_n)).origin - pos_i;
123 Min_Pos = (p3d.project(t3d_n)).origin;
125 //printf("%d %d\n", j, jn);
127 } while (ne < nbSizeTri - 1);
129 if (abs(MinDistance) < abs(dis_n))
131 Min_Pt /= (-Min_Pt.norm());
133 float d = p3d.distance(PL);
137 if (smoothingLength - d > EPSILON && smoothingLength * smoothingLength - d * d > EPSILON && d > EPSILON)
141 kernGradientMeshPBD(r, smoothingLength)
142 / (samplingDistance * samplingDistance * samplingDistance)
143 * 2.0 * (M_PI) * (1 - d / smoothingLength) //eq 11
144 * AreaSum //p3d.areaTriangle(t3d, smoothingLength)
145 / ((M_PI) * (smoothingLength * smoothingLength - d * d)) //eq 11
146 * t3d.normal().dot(Min_Pt) / t3d.normal().norm();
149 Coord g = a_ij * (pos_i - nearest_pt.origin) / r;
155 grad_ci *= (dis_n / abs(dis_n));
156 lamda_i *= (dis_n / abs(dis_n));
158 //traditional integration position based fluids
159 List<int>& parList_i = neighbors[pId];
160 int nbSize = parList_i.size();
161 for (int ne = 0; ne < nbSize; ne++)
163 int j = parList_i[ne];
165 Real r = (pos_i - posArr[j]).norm();
168 Coord g = kern.Gradient(r, smoothingLength) * (pos_i - posArr[j]) * (1.0f / r);
174 lamda_i += grad_ci.dot(grad_ci);
176 Real rho_i = rhoArr[pId];
178 lamda_i = -(rho_i - 1000.0f) / (lamda_i + 0.1f);
180 lambdaArr[pId] = lamda_i > 0.0f ? 0.0f : lamda_i;
183 template <typename Real, typename Coord>
184 __global__ void K_ComputeDisplacementMesh(
186 DArray<Real> lambdas,
187 DArray<Coord> posArr,
188 DArray<TopologyModule::Triangle> Tri,
189 DArray<Coord> positionTri,
190 DArrayList<int> neighbors,
191 DArrayList<int> neighborsTri,
192 SpikyKernel<Real> kern,
193 Real smoothingLength,
195 Real sampling_distance)
197 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
198 if (pId >= posArr.size())
201 Coord pos_i = posArr[pId];
202 Real lamda_i = lambdas[pId];
205 List<int>& list_i = neighbors[pId];
206 int nbSize = list_i.size();
208 List<int>& triList_i = neighborsTri[pId];
209 int nbSizeTri = triList_i.size();
210 Real dis_n = REAL_MAX;
211 for (int ne = 0; ne < nbSizeTri; ne++)
213 int j = triList_i[ne];
214 Triangle3D t3d(positionTri[Tri[j][0]], positionTri[Tri[j][1]], positionTri[Tri[j][2]]);
215 Plane3D PL(positionTri[Tri[j][0]], t3d.normal());
217 if (abs(p3d.distance(t3d)) < abs(dis_n))
219 dis_n = p3d.distance(t3d);
222 //semi-analytical boundary integration
223 for (int ne = 0; ne < nbSizeTri; ne++)
225 int j = triList_i[ne];
226 Triangle3D t3d(positionTri[Tri[j][0]], positionTri[Tri[j][1]], positionTri[Tri[j][2]]);
227 Plane3D PL(positionTri[Tri[j][0]], t3d.normal());
229 //Point3D nearest_pt = p3d.project(t3d);
230 Point3D nearest_pt = p3d.project(PL);
231 Real r = (nearest_pt.origin - pos_i).norm();
234 float d = p3d.distance(PL);
236 Coord ttm = PL.normal;
237 Real AreaSum = calculateIntersectionArea(p3d, t3d, smoothingLength); //A_s in equation 10
238 Real MinDistance = abs(p3d.distance(t3d)); //d_n (scalar) in equation 10
239 Coord Min_Pt = (p3d.project(t3d)).origin - pos_i; //d_n (vector) in equation 10
240 Coord Min_Pos = p3d.project(t3d).origin;
241 if (ne < nbSizeTri - 1 && triList_i[ne + 1] < 0)
243 //triangle clustering
247 jn = triList_i[ne + 1];
248 Triangle3D t3d_n(positionTri[Tri[jn][0]], positionTri[Tri[jn][1]], positionTri[Tri[jn][2]]);
249 if ((t3d.normal().cross(t3d_n.normal())).norm() > EPSILON)
252 AreaSum += calculateIntersectionArea(p3d, t3d_n, smoothingLength);
254 if (abs(p3d.distance(t3d_n)) < abs(MinDistance))
256 MinDistance = (p3d.distance(t3d_n));
257 Min_Pt = (p3d.project(t3d_n)).origin - pos_i;
258 Min_Pos = (p3d.project(t3d_n)).origin;
260 //printf("%d %d\n", j, jn);
262 } while (ne < nbSizeTri - 1);
265 Min_Pt /= (-Min_Pt.norm());
268 //r = max((r - sampling_distance / 2.0), 0.0);
269 if (smoothingLength - d > EPSILON && smoothingLength * smoothingLength - d * d > EPSILON && d > EPSILON)
273 kernGradientMeshPBD(r, smoothingLength)
274 * 2.0 * (M_PI) * (1 - d / smoothingLength) //eq 11
275 * AreaSum //p3d.areaTriangle(t3d, smoothingLength)
276 / ((M_PI) * (smoothingLength * smoothingLength - d * d)) // eq11
277 * t3d.normal().dot(Min_Pt) / t3d.normal().norm() // / (p3d.project(t3d).origin - p3d.origin).norm()
278 / (sampling_distance * sampling_distance * sampling_distance);
279 //a_ij *= (dis_n / abs(dis_n));
281 Coord dp_ij = 40.0f * (pos_i - nearest_pt.origin) * (lamda_i)*a_ij * (1.0 / (pos_i - nearest_pt.origin).norm());
287 atomicAdd(&dPos[pId][0], dp_ij[0]);
289 if (Coord::dims() >= 2)
290 atomicAdd(&dPos[pId][1], dp_ij[1]);
292 if (Coord::dims() >= 3)
293 atomicAdd(&dPos[pId][2], dp_ij[2]);
298 //traditional integration position based fluids
299 for (int ne = 0; ne < nbSize; ne++)
302 Real r = (pos_i - posArr[j]).norm();
305 Coord dp_ij = 10.0f * (pos_i - posArr[j]) * (lamda_i + lambdas[j]) * kern.Gradient(r, smoothingLength) * (1.0 / r);
308 atomicAdd(&dPos[pId][0], dp_ij[0]);
309 atomicAdd(&dPos[j][0], -dp_ij[0]);
311 if (Coord::dims() >= 2)
313 atomicAdd(&dPos[pId][1], dp_ij[1]);
314 atomicAdd(&dPos[j][1], -dp_ij[1]);
317 if (Coord::dims() >= 3)
319 atomicAdd(&dPos[pId][2], dp_ij[2]);
320 atomicAdd(&dPos[j][2], -dp_ij[2]);
326 template <typename Coord>
327 __global__ void K_UpdatePositionMesh(
328 DArray<Coord> posArr,
331 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
332 if (pId >= posArr.size())
335 posArr[pId] += dPos[pId];
338 template <typename Real, typename Coord>
339 __global__ void DP_UpdateVelocityMesh(
340 DArray<Coord> velArr,
341 DArray<Coord> prePos,
342 DArray<Coord> curPos,
345 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
346 if (pId >= velArr.size())
349 velArr[pId] += (curPos[pId] - prePos[pId]) / dt;
352 template <typename TDataType>
353 void SemiAnalyticalPBD<TDataType>::takeOneIteration()
355 auto& inPos = this->inPosition()->getData();
357 auto ts = this->inTriangleSet()->constDataPtr();
358 auto& triVertex = ts->getPoints();
359 auto& triIndex = ts->getTriangles();
362 mCalculateDensity->update();
364 int num = inPos.size();
367 K_ComputeLambdasMesh,
369 mCalculateDensity->outDensity()->getData(),
373 this->inNeighborParticleIds()->getData(),
374 this->inNeighborTriangleIds()->getData(),
376 this->inSmoothingLength()->getData(),
377 this->inSamplingDistance()->getData());
380 K_ComputeDisplacementMesh,
386 this->inNeighborParticleIds()->getData(),
387 this->inNeighborTriangleIds()->getData(),
389 this->inSmoothingLength()->getData(),
390 this->inTimeStep()->getData(),
391 this->inSamplingDistance()->getData());
394 K_UpdatePositionMesh,
399 template <typename TDataType>
400 void SemiAnalyticalPBD<TDataType>::updateVelocity()
402 int num = this->inPosition()->size();
404 DP_UpdateVelocityMesh,
405 this->inVelocity()->getData(),
407 this->inPosition()->getData(),
408 this->inTimeStep()->getData());
411 DEFINE_CLASS(SemiAnalyticalPBD);