PeriDyno 1.0.0
Loading...
Searching...
No Matches
SurfaceEnergyForce.cu
Go to the documentation of this file.
1#include "SurfaceEnergyForce.h"
2
3namespace dyno
4{
5 template<typename TDataType>
6 SurfaceEnergyForce<TDataType>::SurfaceEnergyForce()
7 : ParticleApproximation<TDataType>()
8 {
9 this->varKernelType()->setCurrentKey(ParticleApproximation<TDataType>::EKernelType::KT_Smooth);
10 }
11
12 template<typename TDataType>
13 SurfaceEnergyForce<TDataType>::~SurfaceEnergyForce()
14 {
15 mFreeSurfaceEnergy.clear();
16 }
17
18 //Equation 3
19 template<typename Real, typename Coord, typename Kernel>
20 __global__ void ST_ComputeSurfaceEnergy(
21 DArray<Real> energyArr,
22 DArray<Coord> posArr,
23 DArrayList<int> neighbors,
24 Real smoothingLength,
25 Real samplingDistance,
26 Kernel gradient,
27 Real scale)
28 {
29 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
30 if (pId >= posArr.size()) return;
31
32 Real V_0 = samplingDistance * samplingDistance * samplingDistance;
33
34 Real total_weight = Real(0);
35 Coord dir_i(0);
36
37 Coord pos_i = posArr[pId];
38 List<int>& nbrIds_i = neighbors[pId];
39 int nbSize = nbrIds_i.size();
40 for (int ne = 0; ne < nbSize; ne++)
41 {
42 int j = nbrIds_i[ne];
43 Real r = (pos_i - posArr[j]).norm();
44
45 if (r > EPSILON)
46 {
47 Real weight = -V_0 * gradient(r, smoothingLength, scale);
48 total_weight += weight;
49 dir_i += (posArr[j] - pos_i) * (weight / r);
50 }
51 }
52
53 total_weight = total_weight < EPSILON ? 1.0f : total_weight;
54 Real absDir = dir_i.norm() / total_weight;
55
56 energyArr[pId] = absDir * absDir;
57 }
58
59 //Equation 4
60 template<typename Real, typename Coord, typename Kernel>
61 __global__ void ST_ComputeSurfaceTension(
62 DArray<Coord> velArr,
63 DArray<Real> energyArr,
64 DArray<Coord> posArr,
65 DArrayList<int> neighbors,
66 Real smoothingLength,
67 Real samplingDistance,
68 Real kappa,
69 Real density,
70 Real dt,
71 Kernel gradient,
72 Real scale)
73 {
74 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
75 if (pId >= posArr.size()) return;
76
77 Real V_0 = samplingDistance * samplingDistance * samplingDistance;
78
79 //A hack in using 1000000, to be refined in the future
80 Real ceof = 1000000 * kappa;
81
82 Coord F_i(0);
83 Coord dv_pi(0);
84 Coord pos_i = posArr[pId];
85 List<int>& nbrIds_i = neighbors[pId];
86 int nbSize = nbrIds_i.size();
87 for (int ne = 0; ne < nbSize; ne++)
88 {
89 int j = nbrIds_i[ne];
90 Real r = (pos_i - posArr[j]).norm();
91
92 if (r > EPSILON)
93 {
94 Coord F_ij = V_0 * V_0 * gradient(r, smoothingLength, scale) * (posArr[j] - pos_i) * (1.0f / r);
95 F_i += F_ij;
96 }
97 }
98
99 velArr[pId] -= dt * ceof * F_i / (density * V_0);
100 }
101
102 template<typename TDataType>
103 void SurfaceEnergyForce<TDataType>::compute()
104 {
105 Real kappa = this->varKappa()->getValue();
106 Real rho = this->varRestDensity()->getValue();
107
108 auto dt = this->inTimeStep()->getValue();
109
110 auto& pos = this->inPosition()->constData();
111 auto& vel = this->inVelocity()->getData();
112 auto& neighbors = this->inNeighborIds()->constData();
113
114 auto h = this->inSmoothingLength()->getValue();
115 auto d = this->inSamplingDistance()->getValue();
116
117 int num = pos.size();
118
119 if (num != mFreeSurfaceEnergy.size())
120 mFreeSurfaceEnergy.resize(num);
121
122 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
123 ST_ComputeSurfaceEnergy,
124 mFreeSurfaceEnergy,
125 pos,
126 neighbors,
127 h,
128 d);
129
130 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
131 ST_ComputeSurfaceTension,
132 vel,
133 mFreeSurfaceEnergy,
134 pos,
135 neighbors,
136 h,
137 d,
138 kappa,
139 rho,
140 dt);
141 }
142
143 DEFINE_CLASS(SurfaceEnergyForce);
144}