1#include "DivergenceFreeSphSolver.h"
3#include "SummationDensity.h"
7 template<typename TDataType>
8 DivergenceFreeSphSolver<TDataType>::DivergenceFreeSphSolver()
9 : ParticleApproximation<TDataType>()
11 this->varRestDensity()->setValue(Real(1000));
13 mSummation = std::make_shared<SummationDensity<TDataType>>();
15 this->inSmoothingLength()->connect(mSummation->inSmoothingLength());
16 this->inSamplingDistance()->connect(mSummation->inSamplingDistance());
17 this->inPosition()->connect(mSummation->inPosition());
18 this->inNeighborIds()->connect(mSummation->inNeighborIds());
20 mSummation->outDensity()->connect(this->outDensity());
23 template<typename TDataType>
24 DivergenceFreeSphSolver<TDataType>::~DivergenceFreeSphSolver()
29 mPredictDensity.clear();
35 template <typename Real, typename Coord, typename Kernel>
36 __global__ void DFSPH_AlphaCompute(
40 DArrayList<int> neighbors,
47 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
48 if (pId >= alpha.size()) return;
50 Coord pos_i = posArr[pId];
52 Real inv_alpha_i = Real(0);
55 List<int>& list_i = neighbors[pId];
56 int nbSize = list_i.size();
58 for (int ne = 0; ne < nbSize; ne++)
61 Real r = (pos_i - posArr[j]).norm();
65 Coord g = mass * gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
67 inv_alpha_i += g.dot(g);
71 inv_alpha_i += grad_ci.dot(grad_ci);
73 Real rho_i = rhoArr[pId];
75 if (inv_alpha_i < EPSILON) inv_alpha_i = EPSILON;
77 alpha[pId] = rho_i / (inv_alpha_i);
79 if ((nbSize < 5)) alpha[pId] = 0.0;
81 //if (alpha[pId] > 1.0)
83 // printf("a %f, inv_a %e, rho %f, nb %d \r\n", alpha[pId], inv_alpha_i, rho_i, nbSize);
88 template <typename Real, typename Coord, typename Kernel>
89 __global__ void DFSPH_DensityPredict(
90 DArray<Real> p_rhoArr,
92 DArray<Coord> veloArr,
94 DArrayList<int> neighbors,
103 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
104 if (pId >= p_rhoArr.size()) return;
106 Coord pos_i = posArr[pId];
110 List<int>& list_i = neighbors[pId];
111 int nbSize = list_i.size();
113 for (int ne = 0; ne < nbSize; ne++)
116 Real r = (pos_i - posArr[j]).norm();
120 Coord g = gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
121 div_i += mass * g.dot(veloArr[pId] - veloArr[j]);
124 Real rho_i = rhoArr[pId] > rest_density ? rhoArr[pId] : rest_density;
126 //if (nbSize < 10) div_i = 0;
128 p_rhoArr[pId] = rho_i + dt * div_i;
130 if (p_rhoArr[pId] < rest_density) p_rhoArr[pId] = rest_density;
134 template <typename Real, typename Coord, typename Kernel>
135 __global__ void DFSPH_DivergencePredict(
136 DArray<Real> divergenceArr,
137 DArray<Coord> posArr,
138 DArray<Coord> veloArr,
140 DArrayList<int> neighbors,
144 Real smoothingLength,
149 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
150 if (pId >= divergenceArr.size()) return;
152 Coord pos_i = posArr[pId];
156 List<int>& list_i = neighbors[pId];
157 int nbSize = list_i.size();
159 for (int ne = 0; ne < nbSize; ne++)
162 Real r = (pos_i - posArr[j]).norm();
164 if (r > 100 * EPSILON)
166 Coord g = gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
167 div_i += mass * g.dot(veloArr[pId] - veloArr[j]);
171 if ((div_i < 0) || (nbSize < 10)) div_i = 0;
173 divergenceArr[pId] = div_i;
177 template <typename Real>
178 __global__ void DFSPH_DensityKappa(
179 DArray<Real> KappaArr,
180 DArray<Real> alpahArr,
181 DArray<Real> predict_RhoArr,
186 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
187 if (pId >= KappaArr.size()) return;
188 KappaArr[pId] = alpahArr[pId] * (predict_RhoArr[pId] - rho_0) / (dt * dt);
193 template <typename Real>
194 __global__ void DFSPH_DivergenceKappa(
195 DArray<Real> KappaArr,
196 DArray<Real> alpahArr,
197 DArray<Real> divergence,
202 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
203 if (pId >= KappaArr.size()) return;
205 KappaArr[pId] = 1.0 * alpahArr[pId] * divergence[pId] / (dt);
208 template <typename Real, typename Coord, typename Kernel>
209 __global__ void DFSPH_VelocityUpdatedByKappa(
210 DArray<Coord> veloArr,
211 DArray<Real> KappaArr,
212 DArray<Real> alpahArr,
213 DArray<Coord> posArr,
214 DArray<Real> predict_RhoArr,
216 DArrayList<int> neighbors,
220 Real smoothingLength,
224 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
225 if (pId >= veloArr.size()) return;
227 Coord pos_i = posArr[pId];
229 List<int>& list_i = neighbors[pId];
230 int nbSize = list_i.size();
234 for (int ne = 0; ne < nbSize; ne++)
237 Real r = (pos_i - posArr[j]).norm();
240 Coord g = gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
242 //d_velo += mass * (KappaArr[pId] / rhoArr[pId] + KappaArr[j] / rhoArr[j]) * g;
243 d_velo += mass * (KappaArr[pId] / (rhoArr[pId]) + KappaArr[j] / (rhoArr[j]) ) * g;
247 veloArr[pId] -= dt * d_velo;
250 template<typename TDataType>
251 void DivergenceFreeSphSolver<TDataType>::compute()
253 int num = this->inPosition()->size();
255 if (this->outDensity()->size() != this->inPosition()->size())
256 this->outDensity()->resize(this->inPosition()->size());
258 if (mKappa_r.size() != this->inPosition()->size())
259 mKappa_r.resize(this->inPosition()->size());
261 if (mKappa_v.size() != this->inPosition()->size())
262 mKappa_v.resize(this->inPosition()->size());
264 if (mAlpha.size() != this->inPosition()->size())
265 mAlpha.resize(this->inPosition()->size());
267 if (mPredictDensity.size() != this->inPosition()->size())
268 mPredictDensity.resize(this->inPosition()->size());
270 if (mDivergence.size() != this->inPosition()->size())
271 mDivergence.resize(this->inPosition()->size());
273 mSummation->varRestDensity()->setValue(this->varRestDensity()->getValue());
274 mSummation->varKernelType()->setCurrentKey(this->varKernelType()->currentKey());
275 mSummation->update();
277 int MaxItNum = this->varMaxIterationNumber()->getValue();
279 this->computeAlpha();
282 if (this->varDivergenceSolverDisabled()->getValue() == false)
284 Real v_err = 10000.0f;
285 while ((v_err > this->varDivergenceErrorThreshold()->getValue()) && (it < MaxItNum))
287 v_err = abs(this->takeOneDivergenIteration()) / this->varRestDensity()->getValue();
293 if (this->varDensitySolverDisabled()->getValue() == false)
295 Real d_err = 10000.0f;
296 while ((it < MaxItNum))
298 d_err = abs(this->takeOneDensityIteration());
304 template<typename TDataType>
305 void DivergenceFreeSphSolver<TDataType>::computeAlpha()
308 int num = this->inPosition()->size();
309 Real rho_0 = this->varRestDensity()->getValue();
311 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
314 this->inPosition()->getData(),
315 mSummation->outDensity()->getData(),
316 this->inNeighborIds()->getData(),
318 mSummation->getParticleMass(),
319 this->inSmoothingLength()->getValue()
323 template<typename TDataType>
324 typename TDataType::Real DivergenceFreeSphSolver<TDataType>::takeOneDensityIteration()
326 Real dt = this->inTimeStep()->getData();
327 int num = this->inPosition()->size();
328 Real rho_0 = this->varRestDensity()->getValue();
330 mSummation->update();
332 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
333 DFSPH_DensityPredict,
335 this->inPosition()->getData(),
336 this->inVelocity()->getData(),
337 mSummation->outDensity()->getData(),
338 this->inNeighborIds()->getData(),
339 this->inTimeStep()->getValue(),
341 mSummation->getParticleMass(),
342 this->inSmoothingLength()->getValue()
345 cuExecute(num, DFSPH_DensityKappa,
349 mSummation->outDensity()->getData(),
350 this->inTimeStep()->getValue(),
354 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
355 DFSPH_VelocityUpdatedByKappa,
356 this->inVelocity()->getData(),
359 this->inPosition()->getData(),
361 mSummation->outDensity()->getData(),
362 this->inNeighborIds()->getData(),
363 this->inTimeStep()->getValue(),
365 mSummation->getParticleMass(),
366 this->inSmoothingLength()->getValue()
369// auto m_reduce = Reduction<Real>::Create(num);
370// Real avr_pdensity = m_reduce->average(mPredictDensity.begin(), num);
371// Real err = (avr_pdensity - rho_0) / rho_0;
376 template<typename TDataType>
377 typename TDataType::Real DivergenceFreeSphSolver<TDataType>::takeOneDivergenIteration()
381 Real dt = this->inTimeStep()->getData();
382 int num = this->inPosition()->size();
383 Real rho_0 = this->varRestDensity()->getValue();
385 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
386 DFSPH_DivergencePredict,
388 this->inPosition()->getData(),
389 this->inVelocity()->getData(),
390 mSummation->outDensity()->getData(),
391 this->inNeighborIds()->getData(),
392 this->inTimeStep()->getValue(),
394 mSummation->getParticleMass(),
395 this->inSmoothingLength()->getValue()
398 cuExecute(num, DFSPH_DivergenceKappa,
402 mSummation->outDensity()->getData(),
403 this->inTimeStep()->getValue(),
407 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
408 DFSPH_VelocityUpdatedByKappa,
409 this->inVelocity()->getData(),
412 this->inPosition()->getData(),
414 mSummation->outDensity()->getData(),
415 this->inNeighborIds()->getData(),
416 this->inTimeStep()->getValue(),
418 mSummation->getParticleMass(),
419 this->inSmoothingLength()->getValue()
422 auto m_reduce2 = Reduction<Real>::Create(num);
423 Real avr_div = m_reduce2->average(mDivergence.begin(), num);
429 DEFINE_CLASS(DivergenceFreeSphSolver);