1#include "ApproximateImplicitViscosity.h"
3#include "Algorithm/Function2Pt.h"
9 template<typename TDataType>
10 ApproximateImplicitViscosity<TDataType>::ApproximateImplicitViscosity()
13 this->inAttribute()->tagOptional(true);
18 template<typename Real>
19 __device__ Real VB_FNorm(const Real a, const Real b, const Real c)
22 return sqrt(p * p / 2);
25 //CrossModel Viscosity Coefficient
26 template<typename Real>
27 __device__ Real VB_Viscosity(const Real Viscosity_h, const Real Viscosity_l, const Real StrainRate, const Real CrossModel_K, const Real CrossModel_n)
29 Real p = CrossModel_K * StrainRate;
30 p = pow(p, CrossModel_n);
31 return Viscosity_h + (Viscosity_l - Viscosity_h) / (1 + p);
34 __device__ inline float kernWeight(const float r, const float h)
36 const float q = r / h;
37 if (q > 1.0f) return 0.0f;
39 return (1.0 - pow(q, 4.0f));
43 __device__ inline float kernWR(const float r, const float h)
45 float w = kernWeight(r, h);
46 const float q = r / h;
54 __device__ inline float kernWRR(const float r, const float h)
56 float w = kernWeight(r, h);
57 const float q = r / h;
60 return w / (0.16f*h*h);
65 template <typename Real, typename Coord>
66 __global__ void VC_ComputeAlpha
69 DArray<Coord> position,
70 DArray<Attribute> attribute,
71 DArrayList<int> neighbors,
75 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
76 if (pId >= position.size()) return;
77 if (!attribute[pId].isDynamic()) return;
79 Coord pos_i = position[pId];
82 List<int>& list_i = neighbors[pId];
83 int nbSize = list_i.size();
85 for (int ne = 0; ne < nbSize; ne++)
88 Real r = (pos_i - position[j]).norm();;
92 Real a_ij = kernWeight(r, smoothingLength);
99 template <typename Real>
100 __global__ void VC_CorrectAlpha
105 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
106 if (pId >= alpha.size()) return;
108 Real alpha_i = alpha[pId];
109 if (alpha_i < maxAlpha)
113 alpha[pId] = alpha_i;
117 template <typename Real, typename Coord, typename Matrix>
118 __global__ void VC_VisComput
120 DArray<Coord> velNew,
121 DArray<Coord> velBuf,
122 DArray<Coord> velOld,
124 DArray<Coord> position,
126 DArray<Attribute> attribute,
127 DArrayList<int> neighbor,
134 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
135 if (pId >= position.size()) return;
136 if (!attribute[pId].isDynamic()) return;
141 Real invAlpha_i = 1.0f / alpha[pId];
143 List<int>& list_i = neighbor[pId];
144 int nbSize = list_i.size();
145 for (int ne = 0; ne < nbSize; ne++)
148 Real r = (position[pId] - position[j]).norm();
151 Real wrr_ij = kernWRR(r, h);
152 Real ai = 1.0f / alpha[pId];
153 Real aj = 1.0f / alpha[j];
154 Coord nij = (position[j] - position[pId]) / r;
155 tempValue = 0.25 * dt * (vis[pId] + vis[j]) * (ai + aj) * wrr_ij / rest_density;
156 Avj += tempValue * velBuf[j].dot(nij) * nij;
158 Mij(0, 0) += nij[0] * nij[0]; Mij(0, 1) += nij[0] * nij[1]; Mij(0, 2) += nij[0] * nij[2];
159 Mij(1, 0) += nij[1] * nij[0]; Mij(1, 1) += nij[1] * nij[1]; Mij(1, 2) += nij[1] * nij[2];
160 Mij(2, 0) += nij[2] * nij[0]; Mij(2, 1) += nij[2] * nij[1]; Mij(2, 2) += nij[2] * nij[2];
161 Mii += Mij*tempValue;
164 Mii += Matrix::identityMatrix();
165 velNew[pId] = Mii.inverse()*(velOld[pId] + velDp[pId] + Avj);
169 //Conjugate Gradient Method.
170 template <typename Real, typename Coord>
171 __global__ void VC_Vis_AxComput
174 DArray<Coord> velBuf,
175 DArray<Coord> position,
177 DArray<Attribute> attribute,
178 DArrayList<int> neighbor,
185 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
186 if (pId >= position.size()) return;
187 if (!attribute[pId].isDynamic()) return;
191 Real invAlpha_i = 1.0f / alpha[pId];
193 List<int>& list_i = neighbor[pId];
194 int nbSize = list_i.size();
195 for (int ne = 0; ne < nbSize; ne++)
198 Real r = (position[pId] - position[j]).norm();
201 Real wrr_ij = kernWRR(r, h);
202 Real ai = 1.0f / alpha[pId];
203 Real aj = 1.0f / alpha[j];
204 Coord nij = (position[j] - position[pId]) / r;
205 Coord vij = velBuf[pId] - velBuf[j];
206 tempValue = 2.5 * dt * (vis[pId] + vis[j]) * (ai + aj) * wrr_ij / rest_density;
207 Avi += tempValue * vij.dot(nij) * nij;
211 v_y[3 * pId] = Avi[0];
212 v_y[3 * pId + 1] = Avi[1];
213 v_y[3 * pId + 2] = Avi[2];
217 template <typename Real, typename Coord>
218 __global__ void VC_Vis_r_Comput
222 DArray<Coord> vel_old,
223 DArray<Coord> position,
224 DArray<Attribute> attribute
227 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
228 if (pId >= position.size()) return;
229 if (!attribute[pId].isDynamic()) return;
230 Coord temp_vel = vel_old[pId];
231 v_r[3 * pId] = temp_vel[0] - v_y[3 * pId];
232 v_r[3 * pId + 1] = temp_vel[1] - v_y[3 * pId + 1];
233 v_r[3 * pId + 2] = temp_vel[2] - v_y[3 * pId + 2];
236 template <typename Real, typename Coord>
237 __global__ void VC_Vis_pToVector
241 DArray<Attribute> attribute
244 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
245 if (pId >= attribute.size()) return;
246 if (!attribute[pId].isDynamic()) return;
247 pv[pId][0] = v_p[3 * pId];
248 pv[pId][1] = v_p[3 * pId + 1];
249 pv[pId][2] = v_p[3 * pId + 2];
253 template <typename Real, typename Coord>
254 __global__ void VC_Vis_CoordToReal
256 DArray<Real> veloReal,
258 DArray<Attribute> attribute
261 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
262 if (pId >= attribute.size()) return;
263 if (!attribute[pId].isDynamic()) return;
264 veloReal[3 * pId] = vel[pId][0];
265 veloReal[3 * pId + 1] = vel[pId][1];
266 veloReal[3 * pId + 2] = vel[pId][2];
269 template <typename Real, typename Coord>
270 __global__ void VC_Vis_RealToVeloctiy
273 DArray<Real> veloReal,
274 DArray<Attribute> attribute
277 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
278 if (pId >= vel.size()) return;
279 if (!attribute[pId].isDynamic()) return;
280 vel[pId][0] = veloReal[3 * pId];
281 vel[pId][1] = veloReal[3 * pId + 1];
282 vel[pId][2] = veloReal[3 * pId + 2];
285 template <typename Real, typename Coord>
286 __global__ void VC_CrossVis
288 DArray<Real> crossVis,
289 DArray<Coord> velBuf,
290 DArray<Coord> position,
292 DArray<Attribute> attribute,
293 DArrayList<int> neighbor,
294 Real smoothingLength,
301 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
302 if (pId >= position.size()) return;
303 if (!attribute[pId].isDynamic()) return;
305 Coord pos_i = position[pId];
306 Coord vel_i = velBuf[pId];
307 Real invAlpha_i = 1.0f / alpha[pId];
312 List<int>& list_i = neighbor[pId];
313 int nbSize = list_i.size();
314 for (int ne = 0; ne < nbSize; ne++)
317 Real r = (position[pId] - position[j]).norm();
320 Real wr_ij = kernWR(r, smoothingLength);
321 Coord g = -invAlpha_i*(pos_i - position[j])*wr_ij*(1.0f / r);
322 vij = 0.5*(velBuf[pId] - velBuf[j]);
323 dv[0] += vij[0] * g[0];
324 dv[1] += vij[1] * g[1];
325 dv[2] += vij[2] * g[2];
329 Real Norm = VB_FNorm(dv[0], dv[1], dv[2]);
330 crossVis[pId] = VB_Viscosity(visTop, visFloor, Norm, K, N);
331 if (pId == 100) printf("viscosity : %f\r\n", crossVis[pId]);
334 template <typename Real, typename Coord>
335 __global__ void VC_updateScar
338 DArray<Coord> velocity
341 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
342 if (pId >= velocity.size()) return;
344 scar[pId] = velocity[pId].norm();
348 __global__ void VC_AttributeInit
350 DArray<Attribute> atts
353 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
354 if (pId >= atts.size()) return;
356 atts[pId].setFluid();
357 atts[pId].setDynamic();
360 template <typename Real>
361 __global__ void VC_ViscosityValueUpdate
363 DArray<Real> viscosities,
367 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
368 if (pId >= viscosities.size()) return;
369 viscosities[pId] = viscosityValue;
372 template<typename TDataType>
373 ApproximateImplicitViscosity<TDataType>::~ApproximateImplicitViscosity()
383 template<typename TDataType>
384 bool ApproximateImplicitViscosity<TDataType>::SetCross()
386 CrossVisCeil = this->varViscosity()->getValue();
387 CrossVisFloor = this->varLowerBoundViscosity()->getValue();
388 CrossVisFloor = CrossVisFloor < CrossVisCeil ? CrossVisFloor : CrossVisCeil;
390 Cross_K = this->varCrossK()->getValue();
391 Cross_N = this->varCrossN()->getValue();
392 std::cout << "*Non-Newtonian Fluid, Viscosity:" << CrossVisFloor
393 << " to " << CrossVisCeil << ", Cross_K:"
394 << Cross_K << ", Cross_N:" << Cross_N
399 template<typename TDataType>
400 void ApproximateImplicitViscosity<TDataType>::constrain()
402 std::cout << "*Approximate Vicosity Solver::Dynamic Viscosity: " << this->varViscosity()->getValue() << std::endl;
404 int num = this->inPosition()->size();
406 if ((num != m_alpha.size())||
407 (num != velOld.size()) ||
408 (num != m_viscosity.size()))
415 m_VelocityReal.resize(3 * num);
418 m_viscosity.resize(num);
419 m_reduce = Reduction<float>::Create(num);
420 m_arithmetic_v = Arithmetic<float>::Create(3 * num);
423 Real dt = this->inTimeStep()->getValue();
425 if (this->inAttribute()->isEmpty() || this->inAttribute()->size()!= this->inPosition()->size())
427 this->inAttribute()->allocate();
428 this->inAttribute()->resize(this->inPosition()->size());
429 cuExecute(num, VC_AttributeInit, this->inAttribute()->getData());
432 auto& m_position = this->inPosition()->getData();
433 auto& m_velocity = this->inVelocity()->getData();
434 auto& m_neighborhood = this->inNeighborIds()->getData();
435 auto& m_attribute = this->inAttribute()->getData();
436 auto m_smoothingLength = this->varSmoothingLength()->getValue();
437 auto m_restDensity = this->varRestDensity()->getValue();
439 cuExecute(num, VC_ViscosityValueUpdate,
441 this->varViscosity()->getValue()
445 cuExecute(num, VC_ComputeAlpha,
452 //VC_CorrectAlpha << <pDims, BLOCK_SIZE >> > (
456 //IF Cross Model is active, viscous coefficients should be computed.
459 if (this->varFluidType()->getValue() == FluidType::NonNewtonianFluid)
462 cuExecute(num, VC_CrossVis,
477 velOld.assign(m_velocity);
480 cuExecute(num, VC_Vis_AxComput,
494 cuExecute(num, VC_Vis_r_Comput,
504 Real Vrr = m_arithmetic_v->Dot(v_r, v_r);
505 Real Verr = sqrt(Vrr / v_r.size());
509 std::cout <<"*Approximate Vicosity Solver::Residual:" << Vrr <<std::endl;
510 while (VisItor < 1000 && Verr / initErr > 0.01f && Vrr > 1000.0f * EPSILON)
513 // //The type of "v_p" should convert to DArray<Coord>
514 cuExecute(num, VC_Vis_pToVector,
521 cuExecute(num, VC_Vis_AxComput,
534 float alpha = Vrr / m_arithmetic_v->Dot(v_p, v_y);
536 cuExecute(num, VC_Vis_CoordToReal,
542 Function2Pt::saxpy(m_VelocityReal, v_p, m_VelocityReal, alpha);
544 cuExecute(num, VC_Vis_RealToVeloctiy,
550 Function2Pt::saxpy(v_r, v_y, v_r, -alpha);
553 Vrr = m_arithmetic_v->Dot(v_r, v_r);
554 Real beta = Vrr / Vrr_old;
555 Function2Pt::saxpy(v_p, v_p, v_r, beta);
557 Verr = sqrt(Vrr / v_r.size());
559 std::cout << "*Approximate Vicosity Solver::Iteration #" << VisItor << ", Relative Resisual:" << Verr / initErr << std::endl;
562 DEFINE_CLASS(ApproximateImplicitViscosity);