1#include "ImplicitISPH.h"
3#include "SummationDensity.h"
7 template<typename TDataType>
8 ImplicitISPH<TDataType>::ImplicitISPH()
9 : ParticleApproximation<TDataType>()
11 //this->varIterationNumber()->setValue(3);
12 this->varKappa()->setValue(200);
13 this->varRestDensity()->setValue(Real(1000));
15 mSummation = std::make_shared<SummationDensity<TDataType>>();
17 this->inSmoothingLength()->connect(mSummation->inSmoothingLength());
18 this->inSamplingDistance()->connect(mSummation->inSamplingDistance());
19 this->inPosition()->connect(mSummation->inPosition());
20 this->inNeighborIds()->connect(mSummation->inNeighborIds());
22 mSummation->outDensity()->connect(this->outDensity());
25 template<typename TDataType>
26 ImplicitISPH<TDataType>::~ImplicitISPH()
36 mPredictDensity.clear();
43 *@Equation: Source_i = rho_0 - (rho_i + dt * div(vi))
45 template <typename Real, typename Coord, typename Kernel>
46 __global__ void IISPH_SourceTermCompute(
49 DArray<Coord> veloArr,
51 DArrayList<int> neighbors,
60 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
61 if (pId >= Sources.size()) return;
63 Coord pos_i = posArr[pId];
67 List<int>& list_i = neighbors[pId];
68 int nbSize = list_i.size();
70 for (int ne = 0; ne < nbSize; ne++)
73 Real r = (pos_i - posArr[j]).norm();
77 Coord g = gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
78 div_i += mass * g.dot(veloArr[pId] - veloArr[j]);
82 Sources[pId] = rest_density - (rhoArr[pId] + dt * div_i);
84 if (Sources[pId] > 0.0f) Sources[pId] = 0.0f;
89 *@Equation: Coord D_ii = - dt^2 * sum_j { mass/(rho_i)^2 * Grad_Wij }
91 template <typename Real, typename Coord, typename Kernel>
92 __global__ void IISPH_DiiCoefficientOfPpeCompute(
96 DArrayList<int> neighbors,
100 Real smoothingLength,
105 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
106 if (pId >= D.size()) return;
108 Coord pos_i = posArr[pId];
112 List<int>& list_i = neighbors[pId];
113 int nbSize = list_i.size();
115 for (int ne = 0; ne < nbSize; ne++)
118 Real r = (pos_i - posArr[j]).norm();
122 Coord g = gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
123 sum -= mass / (rhoArr[pId] * rhoArr[pId]) * g;
127 D[pId] = sum * dt * dt;
133 *@Equation: Coord A_ii = - sum_j { mass (D_ii - D_ji) Grad_Wij };
134 * D_ij = - dt^2 * mass / rho_i^2 * Grad_Wij;
136 template <typename Real, typename Coord, typename Kernel>
137 __global__ void IISPH_AiiCoefficientOfPpeCompute(
140 DArray<Coord> posArr,
142 DArrayList<int> neighbors,
146 Real smoothingLength,
150 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
151 if (pId >= Aii.size()) return;
153 Coord pos_i = posArr[pId];
157 List<int>& list_i = neighbors[pId];
158 int nbSize = list_i.size();
162 for (int ne = 0; ne < nbSize; ne++)
165 Real r = (pos_i - posArr[j]).norm();
169 Coord g_ij = gradient(r, smoothingLength, scale) * (pos_i - posArr[j] ) * (1.0f / r);
170 Coord g_ji = gradient(r, smoothingLength, scale) * (posArr[j] - pos_i) * (1.0f / r);
171 dji = -1.0 * dt * dt * mass * g_ji / (rhoArr[pId] * rhoArr[pId]); //grad_W_ij ???(-1)
172 sum += mass * g_ij.dot(Dii[pId] - dji); //grad_W_ji ???
181 *@Equation: Coord DijPj = D_ij * Pj;
182 * D_ij = - dt^2 * mass * Grad_Wij * Pj / rho_i^2 ;
184 template <typename Real, typename Coord, typename Kernel>
185 __global__ void IISPH_Sum_DijDotPjInPPE(
186 DArray<Coord> SumDijPj,
187 DArray<Real> pressures,
188 DArray<Coord> posArr,
190 DArrayList<int> neighbors,
194 Real smoothingLength,
198 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
199 if (pId >= SumDijPj.size()) return;
201 Coord pos_i = posArr[pId];
203 List<int>& list_i = neighbors[pId];
204 int nbSize = list_i.size();
208 for (int ne = 0; ne < nbSize; ne++)
211 Real r_ij = (pos_i - posArr[j]).norm();
214 Coord g_ij = gradient(r_ij, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r_ij);
215 sum -= dt * dt * mass * g_ij * pressures[j] / (rhoArr[j] * rhoArr[j]);
222 *@Equation: Coord AnPn = sum_n {An * Pn} - Aij;
223 * AnPn = Sum_j { mass * {(Sum_j Dij * Pj) - D_jj * Pj - Sum_(k!=i) D_jk * Pj } Grad_Wij};
225 template <typename Real, typename Coord, typename Kernel>
226 __global__ void IISPH_AnDotPnInPPE(
228 DArray<Real> pressures,
230 DArray<Coord> SumDijPj,
231 DArray<Coord> posArr,
233 DArrayList<int> neighbors,
237 Real smoothingLength,
242 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
243 if (pId >= AnPn.size()) return;
245 Coord pos_i = posArr[pId];
247 List<int>& list_i = neighbors[pId];
248 int nbSize = list_i.size();
255 Coord sum_DjkPk(0.0f);
259 for (int ne = 0; ne < nbSize; ne++)
263 Real r_ij = (pos_i - posArr[j]).norm();
267 Coord g_ij = gradient(r_ij, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r_ij);
269 //Coord g_ji = gradient(r_ij, smoothingLength, scale) * (posArr[j] - pos_i) * (1.0f / r_ij);
271 //Coord d_ji = -dt * dt * mass * g_ji / (rhoArr[pId] * rhoArr[pId]);
273 //sum += mass * g_ij.dot(SumDijPj[pId] - Dii[j] * pressures[j] - (SumDijPj[j] - d_ji * pressures[pId] ));
275 //Coord sumDjkPk = SumDijPj[j];
278 List<int>& list_j = neighbors[j];
279 for (int nj = 0; nj < list_j.size(); nj++)
282 Real r_jk = (posArr[j] - posArr[k]).norm();
283 if (r_jk > EPSILON && k != pId)
285 Coord g_jk = gradient(r_jk, smoothingLength, scale) * (posArr[j] - posArr[k]) * (1.0f / r_jk);
286 d_jk = (-dt * dt * mass / (rhoArr[k] * rhoArr[k])) * g_jk;
288 sumDjkPk += d_jk * pressures[k];
292 sum += mass * g_ij.dot(SumDijPj[pId] - Dii[j] * pressures[j] - sumDjkPk);
300 *@Brief: Relaxed Jacobi Method.
301 *@Equation: pressure_new[i] = Omega * pressure_old[i] + (1 - Omega) * (source[pId] - AnPn) / Aii
304 template <typename Real>
305 __global__ void IISPH_PressureJacobiCompute(
306 DArray<Real> pressures,
307 DArray<Real> oldPressures,
311 DArray<Real> Residual,
315 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
316 if (pId >= pressures.size()) return;
319 if (abs(Aii[pId]) > EPSILON)
321 pressures[pId] = oldPressures[pId] * (1.0 - omega) + omega * (Source[pId] - AnPn[pId]) / Aii[pId];
324 pressures[pId] = 0.0f;
328 *@note Clamping negative pressures will lead to incorrect estimation of the residual in the PPE.
330 //if (pressures[pId] < 0.0f)
331 // pressures[pId] = 0.0f;
333 Residual[pId] = abs(Source[pId] - AnPn[pId] - Aii[pId]* pressures[pId]);
339 template<typename TDataType>
340 void ImplicitISPH<TDataType>::compute()
342 int num = this->inPosition()->size();
344 if (this->outDensity()->size() != this->inPosition()->size())
345 this->outDensity()->resize(this->inPosition()->size());
347 if (mPredictDensity.size() != this->inPosition()->size())
348 mPredictDensity.resize(this->inPosition()->size());
350 if (mDensityAdv.size() != this->inPosition()->size())
351 mDensityAdv.resize(this->inPosition()->size());
353 if (mPressrue.size() != this->inPosition()->size())
354 mPressrue.resize(this->inPosition()->size());
356 if (mSourceTerm.size() != this->inPosition()->size())
357 mSourceTerm.resize(this->inPosition()->size());
359 if (mDii.size() != this->inPosition()->size())
360 mDii.resize(this->inPosition()->size());
362 if (mAii.size() != this->inPosition()->size())
363 mAii.resize(this->inPosition()->size());
365 if (mAnPn.size() != this->inPosition()->size())
366 mAnPn.resize(this->inPosition()->size());
368 if (mPressrue.size() != this->inPosition()->size())
369 mPressrue.resize(this->inPosition()->size());
371 if (mSumDijPj.size() != this->inPosition()->size())
372 mSumDijPj.resize(this->inPosition()->size());
374 if (m_Residual.size() != this->inPosition()->size())
375 m_Residual.resize(this->inPosition()->size());
377 if (mOldPressrue.size() != this->inPosition()->size())
378 mOldPressrue.resize(this->inPosition()->size());
381 mSummation->varRestDensity()->setValue(this->varRestDensity()->getValue());
382 mSummation->varKernelType()->setCurrentKey(this->varKernelType()->currentKey());
383 mSummation->update();
385 this->PreIterationCompute();
389 int itNum = this->varIterationNumber()->getValue();
391 mOldPressrue.reset();
394// Real error_max = takeOneIteration();
395// Real error = error_max;
397 while ( (it++ < itNum))
400 //std::cout << "Residual: " << error / error_max * 100.0f << "%" << std::endl;
407 template<typename TDataType>
408 void ImplicitISPH<TDataType>::PreIterationCompute()
410 Real dt = this->inTimeStep()->getData();
411 int num = this->inPosition()->size();
412 Real rho_0 = this->varRestDensity()->getValue();
414 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
415 IISPH_DiiCoefficientOfPpeCompute,
417 this->inPosition()->getData(),
418 mSummation->outDensity()->getData(),
419 this->inNeighborIds()->getData(),
420 this->inTimeStep()->getValue(),
422 mSummation->getParticleMass(),
423 this->inSmoothingLength()->getValue()
426 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
427 IISPH_SourceTermCompute,
429 this->inPosition()->getData(),
430 this->inVelocity()->getData(),
431 mSummation->outDensity()->getData(),
432 this->inNeighborIds()->getData(),
433 this->inTimeStep()->getValue(),
435 mSummation->getParticleMass(),
436 this->inSmoothingLength()->getValue()
439 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
440 IISPH_AiiCoefficientOfPpeCompute,
443 this->inPosition()->getData(),
444 mSummation->outDensity()->getData(),
445 this->inNeighborIds()->getData(),
446 this->inTimeStep()->getValue(),
448 mSummation->getParticleMass(),
449 this->inSmoothingLength()->getValue()
456 template<typename TDataType>
457 typename TDataType::Real ImplicitISPH<TDataType>::takeOneIteration()
459 Real dt = this->inTimeStep()->getData();
460 int num = this->inPosition()->size();
461 Real rho_0 = this->varRestDensity()->getValue();
463 mOldPressrue.assign(mPressrue);
465// cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
466// IISPH_Sum_DijDotPjInPPE,
469// this->inPosition()->getData(),
470// mSummation->outDensity()->getData(),
471// this->inNeighborIds()->getData(),
472// this->inTimeStep()->getValue(),
474// mSummation->getParticleMass(),
475// this->inSmoothingLength()->getValue()
478 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
484 this->inPosition()->getData(),
485 mSummation->outDensity()->getData(),
486 this->inNeighborIds()->getData(),
487 this->inTimeStep()->getValue(),
489 mSummation->getParticleMass(),
490 this->inSmoothingLength()->getValue()
494 cuExecute(num, IISPH_PressureJacobiCompute,
501 this->varRelaxedOmega()->getValue()
504// auto m_reduce = Reduction<Real>::Create(num);
505// Real error = m_reduce->average(m_Residual.begin(), num) / num;
511 template <typename Real, typename Coord, typename Kernel>
512 __global__ void IISPH_UpdateVelocity(
513 DArray<Coord> velocities,
514 DArray<Real> pressures,
515 DArray<Coord> posArr,
517 DArrayList<int> neighbors,
521 Real smoothingLength,
525 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
526 if (pId >= velocities.size()) return;
530 List<int>& list_i = neighbors[pId];
531 int nbSize = list_i.size();
533 for (int ne = 0; ne < nbSize; ne++)
536 Real r_ij = (posArr[pId] - posArr[j]).norm();
539 Coord g_ij = gradient(r_ij, smoothingLength, scale) * (posArr[pId] - posArr[j]) * (1.0f / r_ij);
540 Force_i -= mass * mass * (pressures[pId] / (rhoArr[pId] * rhoArr[pId]) + pressures[j] / (rhoArr[j] * rhoArr[j])) * g_ij;
544 velocities[pId] += dt * Force_i / mass;
547 template<typename TDataType>
548 void ImplicitISPH<TDataType>::updateVelocity()
550 int num = this->inPosition()->size();
551 Real dt = this->inTimeStep()->getData();
552 Real rho_0 = this->varRestDensity()->getValue();
554 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
555 IISPH_UpdateVelocity,
556 this->inVelocity()->getData(),
558 this->inPosition()->getData(),
559 mSummation->outDensity()->getData(),
560 this->inNeighborIds()->getData(),
561 this->inTimeStep()->getValue(),
563 mSummation->getParticleMass(),
564 this->inSmoothingLength()->getValue()
570 DEFINE_CLASS(ImplicitISPH);