PeriDyno 1.0.0
Loading...
Searching...
No Matches
IterativeDensitySolver.cu
Go to the documentation of this file.
1#include "IterativeDensitySolver.h"
2
3#include "SummationDensity.h"
4
5namespace dyno
6{
7 template<typename TDataType>
8 IterativeDensitySolver<TDataType>::IterativeDensitySolver()
9 : ParticleApproximation<TDataType>()
10 {
11 this->varIterationNumber()->setValue(3);
12 this->varRestDensity()->setValue(Real(1000));
13
14 this->inAttribute()->tagOptional(true);
15
16 mSummation = std::make_shared<SummationDensity<TDataType>>();
17
18 this->inSmoothingLength()->connect(mSummation->inSmoothingLength());
19 this->inSamplingDistance()->connect(mSummation->inSamplingDistance());
20 this->inPosition()->connect(mSummation->inPosition());
21 this->inNeighborIds()->connect(mSummation->inNeighborIds());
22
23 mSummation->outDensity()->connect(this->outDensity());
24 }
25
26 template<typename TDataType>
27 IterativeDensitySolver<TDataType>::~IterativeDensitySolver()
28 {
29 mLamda.clear();
30 mDeltaPos.clear();
31 mPositionOld.clear();
32 }
33
34
35 template <typename Real, typename Coord, typename Kernel>
36 __global__ void IDS_ComputeLambdas(
37 DArray<Real> lambdaArr,
38 DArray<Coord> posArr,
39 DArrayList<int> neighbors,
40 Real rho_0,
41 Real smoothingLength,
42 Real samplingDistance,
43 Kernel gradient,
44 Real scale)
45 {
46 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
47 if (pId >= posArr.size()) return;
48
49 Coord pos_i = posArr[pId];
50
51 Real gg_i = Real(0);
52 Coord grad_ci(0);
53
54 Real V_0 = samplingDistance * samplingDistance * samplingDistance;
55
56 List<int>& list_i = neighbors[pId];
57 int nbSize = list_i.size();
58 for (int ne = 0; ne < nbSize; ne++)
59 {
60 int j = list_i[ne];
61 Real r = (pos_i - posArr[j]).norm();
62
63 if (r > EPSILON)
64 {
65 Coord g = V_0 * gradient(r, smoothingLength, scale) * (pos_i - posArr[j]) * (1.0f / r);
66 grad_ci += g;
67
68 Real gg_j = g.dot(g);
69
70 atomicAdd(&lambdaArr[pId], gg_j);
71 atomicAdd(&lambdaArr[j], gg_j);
72
73 gg_i += g.dot(g);
74 }
75 }
76
77 gg_i += grad_ci.dot(grad_ci);
78
79 atomicAdd(&lambdaArr[pId], gg_i);
80 }
81
82 template <typename Real>
83 __global__ void IDS_ClumpLambdas(
84 DArray<Real> lambdaArr,
85 DArray<Real> rhoArr,
86 Real rho_0)
87 {
88 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
89 if (pId >= rhoArr.size()) return;
90
91 Real rho_i = rhoArr[pId];
92 Real lambda_i = lambdaArr[pId];
93
94 lambda_i = -(rho_i - rho_0) / (lambda_i + EPSILON) / rho_0;
95
96 lambdaArr[pId] = lambda_i > 0.0f ? 0.0f : lambda_i;
97 }
98
99 template <typename Real, typename Coord, typename Kernel>
100 __global__ void IDS_ComputeDisplacement(
101 DArray<Coord> dPos,
102 DArray<Real> lambdas,
103 DArray<Coord> posArr,
104 DArrayList<int> neighbors,
105 Real smoothingLength,
106 Real samplingDistance,
107 Real kappa,
108 Real rho_0,
109 Real dt,
110 Kernel gradient,
111 Real scale)
112 {
113 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
114 if (pId >= posArr.size()) return;
115
116 Coord pos_i = posArr[pId];
117 Real lamda_i = lambdas[pId];
118
119 Real V_0 = samplingDistance * samplingDistance * samplingDistance;
120
121 Coord dP_i(0);
122 List<int>& list_i = neighbors[pId];
123 int nbSize = list_i.size();
124 for (int ne = 0; ne < nbSize; ne++)
125 {
126 int j = list_i[ne];
127 Real r = (pos_i - posArr[j]).norm();
128 if (r > EPSILON)
129 {
130 Coord dp_ij = V_0 * (pos_i - posArr[j]) * (lamda_i + lambdas[j]) * gradient(r, smoothingLength, scale) * (1.0 / r);
131 dP_i += dp_ij;
132
133 atomicAdd(&dPos[pId][0], dp_ij[0]);
134 atomicAdd(&dPos[j][0], -dp_ij[0]);
135
136 if (Coord::dims() >= 2)
137 {
138 atomicAdd(&dPos[pId][1], dp_ij[1]);
139 atomicAdd(&dPos[j][1], -dp_ij[1]);
140 }
141
142 if (Coord::dims() >= 3)
143 {
144 atomicAdd(&dPos[pId][2], dp_ij[2]);
145 atomicAdd(&dPos[j][2], -dp_ij[2]);
146 }
147 }
148 }
149 }
150
151 template <typename Real, typename Coord>
152 __global__ void IDS_UpdatePosition(
153 DArray<Coord> posArr,
154 DArray<Coord> velArr,
155 DArray<Coord> dPos,
156 Real dt)
157 {
158 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
159 if (pId >= posArr.size()) return;
160
161 posArr[pId] += dPos[pId];
162 }
163
164 template <typename Real, typename Coord>
165 __global__ void IDS_UpdatePosition(
166 DArray<Coord> posArr,
167 DArray<Coord> velArr,
168 DArray<Coord> dPos,
169 DArray<Attribute> attributes,
170 Real dt)
171 {
172 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
173 if (pId >= posArr.size()) return;
174
175 if (attributes[pId].isDynamic())
176 {
177 posArr[pId] += dPos[pId];
178 }
179 }
180
181 template<typename TDataType>
182 void IterativeDensitySolver<TDataType>::compute()
183 {
184 int num = this->inPosition()->size();
185
186 if (mPositionOld.size() != this->inPosition()->size())
187 mPositionOld.resize(this->inPosition()->size());
188
189 mPositionOld.assign(this->inPosition()->getData());
190
191 if (this->outDensity()->size() != this->inPosition()->size())
192 this->outDensity()->resize(this->inPosition()->size());
193
194 if (mDeltaPos.size() != this->inPosition()->size())
195 mDeltaPos.resize(this->inPosition()->size());
196
197 if (mLamda.size() != this->inPosition()->size())
198 mLamda.resize(this->inPosition()->size());
199
200 int it = 0;
201
202 int itNum = this->varIterationNumber()->getValue();
203 while (it++ < itNum)
204 {
205 mSummation->varRestDensity()->setValue(this->varRestDensity()->getValue());
206 mSummation->varKernelType()->setCurrentKey(this->varKernelType()->currentKey());
207 mSummation->update();
208
209 takeOneIteration();
210 }
211
212 updateVelocity();
213 }
214
215
216 template<typename TDataType>
217 void IterativeDensitySolver<TDataType>::takeOneIteration()
218 {
219 Real dt = this->inTimeStep()->getData();
220 int num = this->inPosition()->size();
221 Real rho_0 = this->varRestDensity()->getValue();
222
223 mDeltaPos.reset();
224 mSummation->varRestDensity()->setValue(rho_0);
225 mSummation->varKernelType()->setCurrentKey(this->varKernelType()->currentKey());
226 mSummation->update();
227
228 mLamda.reset();
229
230 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
231 IDS_ComputeLambdas,
232 mLamda,
233 this->inPosition()->getData(),
234 this->inNeighborIds()->getData(),
235 rho_0,
236 this->inSmoothingLength()->getValue(),
237 this->inSamplingDistance()->getValue());
238
239 cuExecute(num,
240 IDS_ClumpLambdas,
241 mLamda,
242 mSummation->outDensity()->constData(),
243 rho_0);
244
245 cuFirstOrder(num, this->varKernelType()->getDataPtr()->currentKey(), this->mScalingFactor,
246 IDS_ComputeDisplacement,
247 mDeltaPos,
248 mLamda,
249 this->inPosition()->getData(),
250 this->inNeighborIds()->getData(),
251 this->inSmoothingLength()->getValue(),
252 this->inSamplingDistance()->getValue(),
253 this->varKappa()->getValue(),
254 rho_0,
255 dt);
256
257 if (this->inAttribute()->isEmpty())
258 {
259 cuExecute(num,
260 IDS_UpdatePosition,
261 this->inPosition()->getData(),
262 this->inVelocity()->getData(),
263 mDeltaPos,
264 dt);
265 }
266 else
267 {
268 cuExecute(num,
269 IDS_UpdatePosition,
270 this->inPosition()->getData(),
271 this->inVelocity()->getData(),
272 mDeltaPos,
273 this->inAttribute()->constData(),
274 dt);
275 }
276 }
277
278 template <typename Real, typename Coord>
279 __global__ void DP_UpdateVelocity(
280 DArray<Coord> velArr,
281 DArray<Coord> curPos,
282 DArray<Coord> prePos,
283 Real dt)
284 {
285 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
286 if (pId >= velArr.size()) return;
287
288 velArr[pId] += (curPos[pId] - prePos[pId]) / dt;
289 }
290
291 template<typename TDataType>
292 void IterativeDensitySolver<TDataType>::updateVelocity()
293 {
294 int num = this->inPosition()->size();
295
296 Real dt = this->inTimeStep()->getData();
297
298 cuExecute(num, DP_UpdateVelocity,
299 this->inVelocity()->getData(),
300 this->inPosition()->getData(),
301 mPositionOld,
302 dt);
303 }
304
305 DEFINE_CLASS(IterativeDensitySolver);
306}