PeriDyno 1.0.0
Loading...
Searching...
No Matches
PCGConstraintSolver.cu
Go to the documentation of this file.
1#include "PCGConstraintSolver.h"
2#include "SharedFuncsForRigidBody.h"
3
4namespace dyno
5{
6 IMPLEMENT_TCLASS(PCGConstraintSolver, TDataType)
7
8 template<typename TDataType>
9 PCGConstraintSolver<TDataType>::PCGConstraintSolver()
10 :ConstraintModule()
11 {
12 this->inContacts()->tagOptional(true);
13 }
14
15 template<typename TDataType>
16 PCGConstraintSolver<TDataType>::~PCGConstraintSolver()
17 {
18
19 }
20
21 template<typename TDataType>
22 void PCGConstraintSolver<TDataType>::initializeJacobian(Real dt)
23 {
24 int constraint_size = 0;
25 int contact_size = this->inContacts()->size();
26
27 auto topo = this->inDiscreteElements()->constDataPtr();
28
29 int ballAndSocketJoint_size = topo->ballAndSocketJoints().size();
30 int sliderJoint_size = topo->sliderJoints().size();
31 int hingeJoint_size = topo->hingeJoints().size();
32 int fixedJoint_size = topo->fixedJoints().size();
33 int pointJoint_size = topo->pointJoints().size();
34
35 if (this->varFrictionEnabled()->getData())
36 {
37 constraint_size += 3 * contact_size;
38 }
39 else
40 {
41 constraint_size = contact_size;
42 }
43
44 if (ballAndSocketJoint_size != 0)
45 {
46 constraint_size += 3 * ballAndSocketJoint_size;
47 }
48
49 if (sliderJoint_size != 0)
50 {
51 constraint_size += 8 * sliderJoint_size;
52 }
53
54 if (hingeJoint_size != 0)
55 {
56 constraint_size += 8 * hingeJoint_size;
57 }
58
59 if (fixedJoint_size != 0)
60 {
61 constraint_size += 6 * fixedJoint_size;
62 }
63
64 if (pointJoint_size != 0)
65 {
66 constraint_size += 3 * pointJoint_size;
67 }
68
69 if (constraint_size == 0)
70 {
71 return;
72 }
73
74 mVelocityConstraints.resize(constraint_size);
75
76 if (contact_size != 0)
77 {
78 if (mContactsInLocalFrame.size() != this->inContacts()->size()) {
79 mContactsInLocalFrame.resize(this->inContacts()->size());
80 }
81
82 setUpContactsInLocalFrame(
83 mContactsInLocalFrame,
84 this->inContacts()->getData(),
85 this->inCenter()->getData(),
86 this->inRotationMatrix()->getData()
87 );
88
89 auto& contacts = this->inContacts()->getData();
90 setUpContactAndFrictionConstraints(
91 mVelocityConstraints,
92 mContactsInLocalFrame,
93 this->inCenter()->getData(),
94 this->inRotationMatrix()->getData(),
95 this->varFrictionEnabled()->getData()
96 );
97 }
98
99 if (ballAndSocketJoint_size != 0)
100 {
101 auto& joints = topo->ballAndSocketJoints();
102 int begin_index = contact_size;
103
104 if (this->varFrictionEnabled()->getData())
105 {
106 begin_index += 2 * contact_size;
107 }
108
109 setUpBallAndSocketJointConstraints(
110 mVelocityConstraints,
111 joints,
112 this->inCenter()->getData(),
113 this->inRotationMatrix()->getData(),
114 begin_index
115 );
116 }
117
118 if (sliderJoint_size != 0)
119 {
120 auto& joints = topo->sliderJoints();
121 int begin_index = contact_size;
122
123 if (this->varFrictionEnabled()->getData())
124 {
125 begin_index += 2 * contact_size;
126 }
127 begin_index += 3 * ballAndSocketJoint_size;
128 setUpSliderJointConstraints(
129 mVelocityConstraints,
130 joints,
131 this->inCenter()->getData(),
132 this->inRotationMatrix()->getData(),
133 this->inQuaternion()->getData(),
134 begin_index
135 );
136 }
137
138 if (hingeJoint_size != 0)
139 {
140 auto& joints = topo->hingeJoints();
141 int begin_index = contact_size + 3 * ballAndSocketJoint_size + 8 * sliderJoint_size;
142 if (this->varFrictionEnabled()->getData())
143 {
144 begin_index += 2 * contact_size;
145 }
146 setUpHingeJointConstraints(
147 mVelocityConstraints,
148 joints,
149 this->inCenter()->getData(),
150 this->inRotationMatrix()->getData(),
151 this->inQuaternion()->getData(),
152 begin_index
153 );
154 }
155
156 if (fixedJoint_size != 0)
157 {
158 auto& joints = topo->fixedJoints();
159 int begin_index = contact_size + 3 * ballAndSocketJoint_size + 8 * sliderJoint_size + 8 * hingeJoint_size;
160 if (this->varFrictionEnabled()->getData())
161 {
162 begin_index += 2 * contact_size;
163 }
164 setUpFixedJointConstraints(
165 mVelocityConstraints,
166 joints,
167 this->inRotationMatrix()->getData(),
168 this->inQuaternion()->getData(),
169 begin_index
170 );;
171 }
172
173 if (pointJoint_size != 0)
174 {
175 auto& joints = topo->pointJoints();
176 int begin_index = contact_size + 3 * ballAndSocketJoint_size + 8 * sliderJoint_size + 8 * hingeJoint_size + 6 * fixedJoint_size;
177 if (this->varFrictionEnabled()->getData())
178 {
179 begin_index += 2 * contact_size;
180 }
181 setUpPointJointConstraints(
182 mVelocityConstraints,
183 joints,
184 this->inCenter()->getData(),
185 begin_index
186 );
187 }
188
189 auto sizeOfRigids = this->inCenter()->size();
190 mContactNumber.resize(sizeOfRigids);
191 mContactNumber.reset();
192
193 mJ.resize(4 * constraint_size);
194 mB.resize(4 * constraint_size);
195 mEta.resize(constraint_size);
196 mLambda.resize(constraint_size);
197 mResidual.resize(constraint_size);
198 mP.resize(constraint_size);
199 tmpArray.resize(constraint_size);
200 mAp.resize(constraint_size);
201 mZ.resize(constraint_size);
202 mCFM.resize(constraint_size);
203 mERP.resize(constraint_size);
204
205 mK_1.resize(constraint_size);
206 mK_2.resize(constraint_size);
207 mK_3.resize(constraint_size);
208
209 mJ.reset();
210 mB.reset();
211 mEta.reset();
212 mLambda.reset();
213 mResidual.reset();
214 tmpArray.reset();
215 mAp.reset();
216 mP.reset();
217 mZ.reset();
218 mCFM.reset();
219 mERP.reset();
220
221
222 mK_1.reset();
223 mK_2.reset();
224 mK_3.reset();
225
226 calculateJacobianMatrix(
227 mJ,
228 mB,
229 this->inCenter()->getData(),
230 this->inInertia()->getData(),
231 this->inMass()->getData(),
232 this->inRotationMatrix()->getData(),
233 mVelocityConstraints
234 );
235
236 buildCFMAndERP(
237 mJ,
238 mB,
239 mVelocityConstraints,
240 mCFM,
241 mERP,
242 this->varFrequency()->getValue(),
243 this->varDampingRatio()->getValue(),
244 dt
245 );
246
247
248 mErrors.resize(constraint_size);
249 mErrors.reset();
250
251 calculateEtaVectorWithERP(
252 mEta,
253 mJ,
254 this->inVelocity()->getData(),
255 this->inAngularVelocity()->getData(),
256 this->inCenter()->getData(),
257 this->inQuaternion()->getData(),
258 mVelocityConstraints,
259 mERP,
260 this->varSlop()->getValue(),
261 dt
262 );
263
264
265 calculateKWithCFM(
266 mVelocityConstraints,
267 mJ,
268 mB,
269 this->inCenter()->getData(),
270 this->inInertia()->getData(),
271 this->inMass()->getData(),
272 mK_1,
273 mK_2,
274 mK_3,
275 mCFM
276 );
277
278
279 if (contact_size != 0)
280 {
281 calculateContactPoints(
282 this->inContacts()->getData(),
283 mContactNumber);
284 }
285 }
286
287
288 template<typename TDataType>
289 void PCGConstraintSolver<TDataType>::constrain()
290 {
291 uint bodyNum = this->inCenter()->size();
292
293 auto topo = this->inDiscreteElements()->constDataPtr();
294
295 mImpulseC.resize(bodyNum * 2);
296 mImpulseExt.resize(bodyNum * 2);
297 mImpulseC.reset();
298 mImpulseExt.reset();
299
300 Real dt = this->inTimeStep()->getData();
301
302 if (this->varGravityEnabled()->getValue())
303 {
304 setUpGravity(
305 mImpulseExt,
306 this->varGravityValue()->getValue(),
307 dt
308 );
309 }
310
311 updateVelocity(
312 this->inAttribute()->getData(),
313 this->inVelocity()->getData(),
314 this->inAngularVelocity()->getData(),
315 mImpulseExt,
316 this->varLinearDamping()->getValue(),
317 this->varAngularDamping()->getValue(),
318 dt
319 );
320
321
322 if (!this->inContacts()->isEmpty() || topo->totalJointSize() > 0)
323 {
324 float r_norm_old = 0.0;
325 float r_norm_new = 0.0;
326 float alpha = 0.0;
327
328
329 initializeJacobian(dt);
330
331 int constraint_size = mVelocityConstraints.size();
332 int contact_size = this->inContacts()->size();
333
334 if (topo->totalJointSize()!= mJointSize)
335 {
336 mJointSize = topo->totalJointSize();
337 mLambdaOldJoint.resize(0);
338 }
339
340 if (mLambdaOldJoint.size() != 0 && topo->totalJointSize() > 0)
341 {
342 if (this->varFrictionEnabled()->getValue())
343 {
344 mLambda.assign(mLambdaOldJoint, constraint_size - 3 * contact_size, 3 * contact_size, 0);
345 }
346 else
347 {
348 mLambda.assign(mLambdaOldJoint, constraint_size - contact_size, contact_size, 0);
349 }
350 }
351 else
352 {
353 if (topo->totalJointSize() > 0)
354 {
355 if (this->varFrictionEnabled()->getValue())
356 {
357 mLambdaOldJoint.resize(constraint_size - 3 * contact_size);
358 mLambdaOldJoint.assign(mLambda, constraint_size - 3 * contact_size, 0, 3 * contact_size);
359 }
360 else
361 {
362 mLambdaOldJoint.resize(constraint_size - contact_size);
363 mLambdaOldJoint.assign(mLambda, constraint_size - contact_size, 0, 3 * contact_size);
364 }
365 }
366 }
367
368 //r = b - Ax
369 calculateLinearSystemLHS(
370 mJ,
371 mB,
372 mImpulseC,
373 mLambda,
374 tmpArray,
375 mCFM,
376 mVelocityConstraints
377 );
378
379 vectorSub(
380 mResidual,
381 tmpArray,
382 mEta,
383 mVelocityConstraints
384 );
385
386
387 // z = M^{-1} r
388 preconditionedResidual(
389 mResidual,
390 mZ,
391 mK_1,
392 mK_2,
393 mK_3,
394 mVelocityConstraints
395 );
396
397 mP.assign(mZ);
398 r_norm_old = vectorNorm(mResidual, mP);
399 float r_norm_init = r_norm_old;
400
401
402 if (r_norm_old > EPSILON)
403 {
404 for (int i = 0; i < this->varIterationNumberForVelocitySolverCG()->getValue(); i++)
405 {
406 // compute Ap
407 mImpulseC.reset();
408 calculateLinearSystemLHS(
409 mJ,
410 mB,
411 mImpulseC,
412 mP,
413 mAp,
414 mCFM,
415 mVelocityConstraints
416 );
417
418 alpha = r_norm_old / vectorNorm(mP, mAp);
419
420 // x += alpha * p
421 vectorMultiplyScale(
422 tmpArray,
423 mP,
424 alpha,
425 mVelocityConstraints
426 );
427 vectorAdd(
428 mLambda,
429 mLambda,
430 tmpArray,
431 mVelocityConstraints
432 );
433 // clamp x
434 vectorClampSupport(
435 mLambda,
436 mVelocityConstraints
437 );
438
439 vectorClampFriction(
440 mLambda,
441 mVelocityConstraints,
442 this->inContacts()->size(),
443 this->varFrictionCoefficient()->getValue()
444 );
445
446
447 // recompute r
448 mImpulseC.reset();
449 calculateLinearSystemLHS(
450 mJ,
451 mB,
452 mImpulseC,
453 mLambda,
454 tmpArray,
455 mCFM,
456 mVelocityConstraints
457 );
458
459
460 vectorSub(
461 mResidual,
462 tmpArray,
463 mEta,
464 mVelocityConstraints
465 );
466
467 mZold.assign(mZ);
468
469 preconditionedResidual(
470 mResidual,
471 mZ,
472 mK_1,
473 mK_2,
474 mK_3,
475 mVelocityConstraints
476 );
477
478 r_norm_new = vectorNorm(mResidual, mZ);
479 float r_norm_true = vectorNorm(mResidual, mResidual);
480 //printf("%lf\n", r_norm_true);
481 if (r_norm_true <= this->varTolerance()->getValue())
482 break;
483
484 float r_norm_spec = vectorNorm(mResidual, mZold);
485
486 // compute p = r + (r_norm_new / r_norm_old) * p
487 Real r_tmp = r_norm_new - r_norm_spec < 0 ? 0 : r_norm_new - r_norm_spec;
488 vectorMultiplyScale(
489 tmpArray,
490 mP,
491 (r_tmp / r_norm_old),
492 mVelocityConstraints
493 );
494 vectorAdd(
495 mP,
496 tmpArray,
497 mZ,
498 mVelocityConstraints);
499 r_norm_old = r_norm_new;
500 }
501
502 mImpulseC.reset();
503 calculateImpulseByLambda(
504 mLambda,
505 mVelocityConstraints,
506 mImpulseC,
507 mB
508 );
509
510 if (this->varFrictionEnabled()->getValue())
511 {
512 mLambdaOldJoint.assign(mLambda, constraint_size - 3 * contact_size, 0, 3 * contact_size);
513 }
514 else
515 {
516 mLambdaOldJoint.assign(mLambda, constraint_size - contact_size, 0, contact_size);
517 }
518 }
519
520 for (int i = 0; i < this->varIterationNumberForVelocitySolverJacobi()->getValue(); i++)
521 {
522 JacobiIterationForCFM(
523 mLambda,
524 mImpulseC,
525 mJ,
526 mB,
527 mEta,
528 mVelocityConstraints,
529 mContactNumber,
530 mK_1,
531 mK_2,
532 mK_3,
533 this->inMass()->getData(),
534 mCFM,
535 this->varFrictionCoefficient()->getData(),
536 this->varGravityValue()->getData(),
537 dt
538 );
539 }
540
541
542 updateVelocity(
543 this->inAttribute()->getData(),
544 this->inVelocity()->getData(),
545 this->inAngularVelocity()->getData(),
546 mImpulseC,
547 this->varLinearDamping()->getValue(),
548 this->varAngularDamping()->getValue(),
549 dt
550 );
551
552 updateGesture(
553 this->inAttribute()->getData(),
554 this->inCenter()->getData(),
555 this->inQuaternion()->getData(),
556 this->inRotationMatrix()->getData(),
557 this->inInertia()->getData(),
558 this->inVelocity()->getData(),
559 this->inAngularVelocity()->getData(),
560 this->inInitialInertia()->getData(),
561 dt
562 );
563
564 }
565 else
566 {
567 updateGesture(
568 this->inAttribute()->getData(),
569 this->inCenter()->getData(),
570 this->inQuaternion()->getData(),
571 this->inRotationMatrix()->getData(),
572 this->inInertia()->getData(),
573 this->inVelocity()->getData(),
574 this->inAngularVelocity()->getData(),
575 this->inInitialInertia()->getData(),
576 dt
577 );
578 }
579
580
581 }
582
583 DEFINE_CLASS(PCGConstraintSolver);
584}