iMSTK
Interactive Medical Simulation Toolkit
PbdBenchmark.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkCapsule.h"
8 #include "imstkCollisionHandling.h"
9 #include "imstkGeometry.h"
10 #include "imstkMath.h"
11 #include "imstkMeshIO.h"
12 #include "imstkPbdModel.h"
13 #include "imstkPbdModelConfig.h"
14 #include "imstkPbdObject.h"
15 #include "imstkPbdObjectCollision.h"
16 #include "imstkPointSetToCapsuleCD.h"
17 #include "imstkPointwiseMap.h"
18 #include "imstkRbdConstraint.h"
19 #include "imstkScene.h"
20 #include "imstkSphere.h"
21 #include "imstkSurfaceMesh.h"
22 #include "imstkSurfaceMeshToCapsuleCD.h"
23 #include "imstkTetrahedralMesh.h"
24 
25 #include <benchmark/benchmark.h>
26 
27 using namespace imstk;
28 
35 static std::shared_ptr<TetrahedralMesh>
36 makeTetGrid(const Vec3d& size, const Vec3i& dim, const Vec3d& center)
37 {
38  auto prismMesh = std::make_shared<TetrahedralMesh>();
39  auto verticesPtr = std::make_shared<VecDataArray<double, 3>>(dim[0] * dim[1] * dim[2]);
40 
41  VecDataArray<double, 3>& vertices = *verticesPtr.get();
42  const Vec3d dx = size.cwiseQuotient((dim - Vec3i(1, 1, 1)).cast<double>());
43  for (int z = 0; z < dim[2]; z++)
44  {
45  for (int y = 0; y < dim[1]; y++)
46  {
47  for (int x = 0; x < dim[0]; x++)
48  {
49  vertices[x + dim[0] * (y + dim[1] * z)] = Vec3i(x, y, z).cast<double>().cwiseProduct(dx) - size * 0.5 + center;
50  }
51  }
52  }
53 
54  // Add connectivity data
55  auto indicesPtr = std::make_shared<VecDataArray<int, 4>>();
56 
57  VecDataArray<int, 4>& indices = *indicesPtr.get();
58  for (int z = 0; z < dim[2] - 1; z++)
59  {
60  for (int y = 0; y < dim[1] - 1; y++)
61  {
62  for (int x = 0; x < dim[0] - 1; x++)
63  {
64  int cubeIndices[8] =
65  {
66  x + dim[0] * (y + dim[1] * z),
67  (x + 1) + dim[0] * (y + dim[1] * z),
68  (x + 1) + dim[0] * (y + dim[1] * (z + 1)),
69  x + dim[0] * (y + dim[1] * (z + 1)),
70  x + dim[0] * ((y + 1) + dim[1] * z),
71  (x + 1) + dim[0] * ((y + 1) + dim[1] * z),
72  (x + 1) + dim[0] * ((y + 1) + dim[1] * (z + 1)),
73  x + dim[0] * ((y + 1) + dim[1] * (z + 1))
74  };
75 
76  // Alternate the pattern so the edges line up on the sides of each voxel
77  if ((z % 2 ^ x % 2) ^ y % 2)
78  {
79  indices.push_back(Vec4i(cubeIndices[0], cubeIndices[7], cubeIndices[5], cubeIndices[4]));
80  indices.push_back(Vec4i(cubeIndices[3], cubeIndices[7], cubeIndices[2], cubeIndices[0]));
81  indices.push_back(Vec4i(cubeIndices[2], cubeIndices[7], cubeIndices[5], cubeIndices[0]));
82  indices.push_back(Vec4i(cubeIndices[1], cubeIndices[2], cubeIndices[0], cubeIndices[5]));
83  indices.push_back(Vec4i(cubeIndices[2], cubeIndices[6], cubeIndices[7], cubeIndices[5]));
84  }
85  else
86  {
87  indices.push_back(Vec4i(cubeIndices[3], cubeIndices[7], cubeIndices[6], cubeIndices[4]));
88  indices.push_back(Vec4i(cubeIndices[1], cubeIndices[3], cubeIndices[6], cubeIndices[4]));
89  indices.push_back(Vec4i(cubeIndices[3], cubeIndices[6], cubeIndices[2], cubeIndices[1]));
90  indices.push_back(Vec4i(cubeIndices[1], cubeIndices[6], cubeIndices[5], cubeIndices[4]));
91  indices.push_back(Vec4i(cubeIndices[0], cubeIndices[3], cubeIndices[1], cubeIndices[4]));
92  }
93  }
94  }
95  }
96 
97  auto uvCoordsPtr = std::make_shared<VecDataArray<float, 2>>(dim[0] * dim[1] * dim[2]);
98 
99  VecDataArray<float, 2>& uvCoords = *uvCoordsPtr.get();
100  for (int z = 0; z < dim[2]; z++)
101  {
102  for (int y = 0; y < dim[1]; y++)
103  {
104  for (int x = 0; x < dim[0]; x++)
105  {
106  uvCoords[x + dim[0] * (y + dim[1] * z)] = Vec2f(static_cast<float>(x) / dim[0], static_cast<float>(z) / dim[2]) * 3.0;
107  }
108  }
109  }
110 
111  // Ensure correct windings
112  for (int i = 0; i < indices.size(); i++)
113  {
114  if (tetVolume(vertices[indices[i][0]], vertices[indices[i][1]], vertices[indices[i][2]], vertices[indices[i][3]]) < 0.0)
115  {
116  std::swap(indices[i][0], indices[i][2]);
117  }
118  }
119 
120  prismMesh->initialize(verticesPtr, indicesPtr);
121  prismMesh->setVertexTCoords("uvs", uvCoordsPtr);
122 
123  return prismMesh;
124 }
125 
129 static void
130 BM_DistanceVolume(benchmark::State& state)
131 {
132  // Setup simulation
133  std::shared_ptr<Scene> scene = std::make_shared<Scene>("PbdBenchmark");
134 
135  double dt = 0.05;
136 
137  // Create PBD object
138  std::shared_ptr<PbdObject> prismObj = std::make_shared<PbdObject>("Prism");
139 
140  // Setup the Geometry
141  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
142  Vec3d(4.0, 4.0, 4.0),
143  Vec3i(state.range(0), state.range(0), state.range(0)),
144  Vec3d(0.0, 0.0, 0.0));
145 
146  // Setup the Parameters
147  std::shared_ptr<PbdModelConfig> pbdParams = std::make_shared<PbdModelConfig>();
148  // Use volume+distance constraints
149  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Volume, 1.0);
150  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 1.0);
151  pbdParams->m_doPartitioning = false;
152  pbdParams->m_gravity = Vec3d(0.0, -1.0, 0.0);
153  pbdParams->m_dt = dt;
154  pbdParams->m_iterations = state.range(1);
155  pbdParams->m_linearDampingCoeff = 0.03;
156 
157  // Setup the Model
158  auto pbdModel = std::make_shared<PbdModel>();
159  pbdModel->configure(pbdParams);
160 
161  // Setup the Object
162  prismObj->setPhysicsGeometry(prismMesh);
163  prismObj->setDynamicalModel(pbdModel);
164  prismObj->getPbdBody()->uniformMassValue = 0.05;
165  // Fix the borders
166  for (int z = 0; z < state.range(0); z++)
167  {
168  for (int y = 0; y < state.range(0); y++)
169  {
170  for (int x = 0; x < state.range(0); x++)
171  {
172  if (y == state.range(0) - 1)
173  {
174  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
175  }
176  }
177  }
178  }
179 
180  // Create the scene
181  scene->addSceneObject(prismObj);
182  scene->initialize();
183 
184  // Setup outputs for results
185  state.counters["DOFs"] = state.range(0) * state.range(0) * state.range(0);
186  state.counters["Tets"] = prismMesh->getNumTetrahedra();
187  state.counters["Iterations"] = state.range(1);
188 
189  // This loop gets timed
190  for (auto _ : state)
191  {
192  scene->advance(dt);
193  }
194 }
195 
196 BENCHMARK(BM_DistanceVolume)
197 ->Unit(benchmark::kMillisecond)
198 ->Name("Distance and Volume Constraints: Tet Mesh")
199 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
200 
204 static void
205 BM_DistanceDihedral(benchmark::State& state)
206 {
207  // Setup
208  auto scene = std::make_shared<Scene>("PbdBenchmark");
209  double dt = 0.05;
210 
211  auto prismObj = std::make_shared<PbdObject>("Prism");
212 
213  // Setup the Geometry
214  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
215  Vec3d(4.0, 4.0, 4.0),
216  Vec3i(state.range(0), state.range(0), state.range(0)),
217  Vec3d(0.0, 0.0, 0.0));
218 
219  std::shared_ptr<SurfaceMesh> surfMesh = prismMesh->extractSurfaceMesh();
220 
221  // Setup the Parameters
222  auto pbdParams = std::make_shared<PbdModelConfig>();
223  // Use distance+dihedral angle
224  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Dihedral, 1.0);
225  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 1.0);
226  pbdParams->m_doPartitioning = false;
227  pbdParams->m_gravity = Vec3d(0.0, -8.0, 0.0);
228  pbdParams->m_dt = dt;
229  pbdParams->m_iterations = state.range(1);
230  pbdParams->m_linearDampingCoeff = 0.03;
231 
232  // Setup the Model
233  auto pbdModel = std::make_shared<PbdModel>();
234  pbdModel->configure(pbdParams);
235 
236  // Setup the Object
237  prismObj->setPhysicsGeometry(surfMesh);
238  prismObj->setDynamicalModel(pbdModel);
239  prismObj->getPbdBody()->uniformMassValue = 0.05;
240  // Fix the borders
241  for (int vert_id = 0; vert_id < surfMesh->getNumVertices(); vert_id++)
242  {
243  auto position = surfMesh->getVertexPosition(vert_id);
244  if (position.y() == 2.0)
245  {
246  prismObj->getPbdBody()->fixedNodeIds.push_back(vert_id);
247  }
248  }
249 
250  scene->addSceneObject(prismObj);
251  scene->initialize();
252 
253  // Setup outputs for results
254  state.counters["DOFs"] = surfMesh->getNumVertices();
255  state.counters["Tris"] = surfMesh->getNumTriangles();
256  state.counters["Iterations"] = state.range(1);
257 
258  // This loop gets timed
259  for (auto _ : state)
260  {
261  scene->advance(dt);
262  }
263 }
264 
265 BENCHMARK(BM_DistanceDihedral)
266 ->Unit(benchmark::kMillisecond)
267 ->Name("Distance and Dihedral Constraints: Surface Mesh")
268 ->ArgsProduct({ { 4, 8, 10, 16, 26, 38 }, { 2, 5, 8 } });
269 // ->ArgsProduct({{4,6,8,10,16,20}, {2, 5, 8}});
270 
274 static void
275 BM_PbdFemStVK(benchmark::State& state)
276 {
277  // Setup simulation
278  auto scene = std::make_shared<Scene>("PbdBenchmark");
279 
280  double dt = 0.05;
281 
282  // Create PBD object
283  auto prismObj = std::make_shared<PbdObject>("Prism");
284 
285  // Setup the Geometry
286  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
287  Vec3d(4.0, 4.0, 4.0),
288  Vec3i(state.range(0), state.range(0), state.range(0)),
289  Vec3d(0.0, 0.0, 0.0));
290 
291  // Setup the Parameters
292  auto pbdParams = std::make_shared<PbdModelConfig>();
293  // Use FEM Tet constraints
294  pbdParams->m_femParams->m_YoungModulus = 5.0;
295  pbdParams->m_femParams->m_PoissonRatio = 0.4;
296  pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::StVK);
297  pbdParams->m_doPartitioning = false;
298  pbdParams->m_gravity = Vec3d(0.0, -1.0, 0.0);
299  pbdParams->m_dt = dt;
300  pbdParams->m_iterations = state.range(1);
301  pbdParams->m_linearDampingCoeff = 0.03;
302 
303  // Setup the Model
304  auto pbdModel = std::make_shared<PbdModel>();
305  pbdModel->configure(pbdParams);
306 
307  // Setup the Object
308  prismObj->setPhysicsGeometry(prismMesh);
309  prismObj->setDynamicalModel(pbdModel);
310  prismObj->getPbdBody()->uniformMassValue = 0.05;
311 
312  // Fix the borders
313  for (int z = 0; z < state.range(0); z++)
314  {
315  for (int y = 0; y < state.range(0); y++)
316  {
317  for (int x = 0; x < state.range(0); x++)
318  {
319  if (y == state.range(0) - 1)
320  {
321  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
322  }
323  }
324  }
325  }
326 
327  // Create the scene
328  scene->addSceneObject(prismObj);
329  scene->initialize();
330 
331  // Setup outputs for results
332  state.counters["DOFs"] = prismMesh->getNumVertices();
333  state.counters["Tets"] = prismMesh->getNumTetrahedra();
334  state.counters["Iterations"] = state.range(1);
335 
336  // This loop gets timed
337  for (auto _ : state)
338  {
339  scene->advance(dt);
340  }
341 }
342 
343 BENCHMARK(BM_PbdFemStVK)
344 ->Unit(benchmark::kMillisecond)
345 ->Name("FEM StVK Constraints: Tet Mesh")
346 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
347 
351 static void
352 BM_PbdFemCorotation(benchmark::State& state)
353 {
354  // Setup simulation
355  auto scene = std::make_shared<Scene>("PbdBenchmark");
356 
357  double dt = 0.05;
358 
359  // Create PBD object
360  auto prismObj = std::make_shared<PbdObject>("Prism");
361 
362  // Setup the Geometry
363  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
364  Vec3d(4.0, 4.0, 4.0),
365  Vec3i(state.range(0), state.range(0), state.range(0)),
366  Vec3d(0.0, 0.0, 0.0));
367 
368  // Setup the Parameters
369  auto pbdParams = std::make_shared<PbdModelConfig>();
370  // Use FEM Tet constraints
371  pbdParams->m_femParams->m_YoungModulus = 5.0;
372  pbdParams->m_femParams->m_PoissonRatio = 0.4;
373  pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::Corotation);
374  pbdParams->m_doPartitioning = false;
375  pbdParams->m_gravity = Vec3d(0.0, -1.0, 0.0);
376  pbdParams->m_dt = dt;
377  pbdParams->m_iterations = state.range(1);
378  pbdParams->m_linearDampingCoeff = 0.03;
379 
380  // Setup the Model
381  auto pbdModel = std::make_shared<PbdModel>();
382  pbdModel->configure(pbdParams);
383 
384  // Setup the Object
385  prismObj->setPhysicsGeometry(prismMesh);
386  prismObj->setDynamicalModel(pbdModel);
387  prismObj->getPbdBody()->uniformMassValue = 0.05;
388 
389  // Fix the borders
390  for (int z = 0; z < state.range(0); z++)
391  {
392  for (int y = 0; y < state.range(0); y++)
393  {
394  for (int x = 0; x < state.range(0); x++)
395  {
396  if (y == state.range(0) - 1)
397  {
398  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
399  }
400  }
401  }
402  }
403 
404  // Create the scene
405  scene->addSceneObject(prismObj);
406  scene->initialize();
407 
408  // Setup outputs for results
409  state.counters["DOFs"] = prismMesh->getNumVertices();
410  state.counters["Tets"] = prismMesh->getNumTetrahedra();
411  state.counters["Iterations"] = state.range(1);
412 
413  // This loop gets timed
414  for (auto _ : state)
415  {
416  scene->advance(dt);
417  }
418 }
419 
420 BENCHMARK(BM_PbdFemCorotation)
421 ->Unit(benchmark::kMillisecond)
422 ->Name("FEM Corotation Constraints: Tet Mesh")
423 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
424 
428 static void
429 BM_PbdFemNeoHookean(benchmark::State& state)
430 {
431  // Setup simulation
432  auto scene = std::make_shared<Scene>("PbdBenchmark");
433 
434  double dt = 0.05;
435 
436  // Create PBD object
437  auto prismObj = std::make_shared<PbdObject>("Prism");
438 
439  // Setup the Geometry
440  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
441  Vec3d(4.0, 4.0, 4.0),
442  Vec3i(state.range(0), state.range(0), state.range(0)),
443  Vec3d(0.0, 0.0, 0.0));
444 
445  // Setup the Parameters
446  auto pbdParams = std::make_shared<PbdModelConfig>();
447  // Use FEM Tet constraints
448  pbdParams->m_femParams->m_YoungModulus = 5.0;
449  pbdParams->m_femParams->m_PoissonRatio = 0.4;
450  pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::NeoHookean);
451  pbdParams->m_doPartitioning = false;
452  pbdParams->m_gravity = Vec3d(0.0, -1.0, 0.0);
453  pbdParams->m_dt = dt;
454  pbdParams->m_iterations = state.range(1);
455  pbdParams->m_linearDampingCoeff = 0.03;
456 
457  // Setup the Model
458  auto pbdModel = std::make_shared<PbdModel>();
459  pbdModel->configure(pbdParams);
460 
461  // Setup the Object
462  prismObj->setPhysicsGeometry(prismMesh);
463  prismObj->setDynamicalModel(pbdModel);
464  prismObj->getPbdBody()->uniformMassValue = 0.05;
465 
466  // Fix the borders
467  for (int z = 0; z < state.range(0); z++)
468  {
469  for (int y = 0; y < state.range(0); y++)
470  {
471  for (int x = 0; x < state.range(0); x++)
472  {
473  if (y == state.range(0) - 1)
474  {
475  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
476  }
477  }
478  }
479  }
480 
481  // Create the scene
482  scene->addSceneObject(prismObj);
483  scene->initialize();
484 
485  // Setup outputs for results
486  state.counters["DOFs"] = prismMesh->getNumVertices();
487  state.counters["Tets"] = prismMesh->getNumTetrahedra();
488  state.counters["Iterations"] = state.range(1);
489 
490  // This loop gets timed
491  for (auto _ : state)
492  {
493  scene->advance(dt);
494  }
495 }
496 
497 BENCHMARK(BM_PbdFemNeoHookean)
498 ->Unit(benchmark::kMillisecond)
499 ->Name("FEM NeoHookean Constraints: Tet Mesh")
500 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
501 
505 static void
506 BM_PbdFemLinear(benchmark::State& state)
507 {
508  // Setup simulation
509  auto scene = std::make_shared<Scene>("PbdBenchmark");
510 
511  double dt = 0.05;
512 
513  // Create PBD object
514  auto prismObj = std::make_shared<PbdObject>("Prism");
515 
516  // Setup the Geometry
517  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
518  Vec3d(4.0, 4.0, 4.0),
519  Vec3i(state.range(0), state.range(0), state.range(0)),
520  Vec3d(0.0, 0.0, 0.0));
521 
522  // Setup the Parameters
523  auto pbdParams = std::make_shared<PbdModelConfig>();
524  // Use FEM Tet constraints
525  pbdParams->m_femParams->m_YoungModulus = 5.0;
526  pbdParams->m_femParams->m_PoissonRatio = 0.4;
527  pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::Linear);
528  pbdParams->m_doPartitioning = false;
529  pbdParams->m_gravity = Vec3d(0.0, -1.0, 0.0);
530  pbdParams->m_dt = dt;
531  pbdParams->m_iterations = state.range(1);
532  pbdParams->m_linearDampingCoeff = 0.03;
533 
534  // Setup the Model
535  auto pbdModel = std::make_shared<PbdModel>();
536  pbdModel->configure(pbdParams);
537 
538  // Setup the Object
539  prismObj->setPhysicsGeometry(prismMesh);
540  prismObj->setDynamicalModel(pbdModel);
541  prismObj->getPbdBody()->uniformMassValue = 0.05;
542 
543  // Fix the borders
544  for (int z = 0; z < state.range(0); z++)
545  {
546  for (int y = 0; y < state.range(0); y++)
547  {
548  for (int x = 0; x < state.range(0); x++)
549  {
550  if (y == state.range(0) - 1)
551  {
552  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
553  }
554  }
555  }
556  }
557 
558  // Create the scene
559  scene->addSceneObject(prismObj);
560  scene->initialize();
561 
562  // Setup outputs for results
563  state.counters["DOFs"] = prismMesh->getNumVertices();
564  state.counters["Tets"] = prismMesh->getNumTetrahedra();
565  state.counters["Iterations"] = state.range(1);
566 
567  // This loop gets timed
568  for (auto _ : state)
569  {
570  scene->advance(dt);
571  }
572 }
573 
574 BENCHMARK(BM_PbdFemLinear)
575 ->Unit(benchmark::kMillisecond)
576 ->Name("FEM Linear Constraints: Tet Mesh")
577 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
578 
583 static void
584 BM_PbdContactDistanceVol(benchmark::State& state)
585 {
586  // Setup simulation
587  auto scene = std::make_shared<Scene>("PbdBenchmark");
588 
589  double dt = 0.05;
590 
591  // Create PBD object
592  auto prismObj = std::make_shared<PbdObject>("Prism");
593 
594  // Setup the mesh Geometry
595  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
596  Vec3d(4.0, 4.0, 4.0),
597  Vec3i(state.range(0), state.range(0), state.range(0)),
598  Vec3d(0.0, 0.0, 0.0));
599 
600  // Create surface mesh for contact
601  std::shared_ptr<SurfaceMesh> surfMesh = prismMesh->extractSurfaceMesh();
602 
603  // Use surface mesh for collision
604  prismObj->setCollidingGeometry(surfMesh);
605 
606  // Force deformation to match between the surface and volume mesh
607  prismObj->setPhysicsToCollidingMap(std::make_shared<PointwiseMap>(prismMesh, surfMesh));
608 
609  // Setup the Parameters
610  auto pbdParams = std::make_shared<PbdModelConfig>();
611  // Use volume+distance
612  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Volume, 0.9);
613  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 0.9);
614  pbdParams->m_doPartitioning = false;
615  pbdParams->m_gravity = Vec3d(0.0, -1.0 / (double)state.range(0), 0.0);
616  pbdParams->m_dt = 0.05;
617  pbdParams->m_iterations = state.range(1);
618  pbdParams->m_linearDampingCoeff = 0.03;
619 
620  // Setup the Model
621  auto pbdModel = std::make_shared<PbdModel>();
622  pbdModel->configure(pbdParams);
623 
624  // Setup the Object
625  prismObj->setPhysicsGeometry(prismMesh);
626  prismObj->setDynamicalModel(pbdModel);
627  prismObj->getPbdBody()->uniformMassValue = 0.05;
628  // Fix the borders
629  for (int z = 0; z < state.range(0); z++)
630  {
631  for (int y = 0; y < state.range(0); y++)
632  {
633  for (int x = 0; x < state.range(0); x++)
634  {
635  if (y == state.range(0) - 1)
636  {
637  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
638  }
639  }
640  }
641  }
642 
643  // Add Capsule for collision
644  auto capsule = std::make_shared<Capsule>();
645  capsule->setRadius(0.5);
646  capsule->setLength(2);
647  capsule->setPosition(Vec3d(0.0, -2.6, 0.0));
648  capsule->setOrientation(Quatd(0.707, 0.0, 0.0, 0.707));
649 
650  // Set up collision
651  std::shared_ptr<CollidingObject> collisionObj = std::make_shared<CollidingObject>("CollidingObject");
652  collisionObj->setCollidingGeometry(capsule);
653  collisionObj->setVisualGeometry(capsule);
654  scene->addSceneObject(collisionObj);
655 
656  std::shared_ptr<PbdObjectCollision> pbdInteraction =
657  std::make_shared<PbdObjectCollision>(prismObj, collisionObj, "SurfaceMeshToCapsuleCD");
658  pbdInteraction->setFriction(0.0);
659  pbdInteraction->setRestitution(0.0);
660 
661  scene->addInteraction(pbdInteraction);
662 
663  // Create the scene
664  scene->addSceneObject(prismObj);
665  scene->initialize();
666 
667  // Set output results
668  state.counters["DOFs"] = prismMesh->getNumVertices();
669  state.counters["Tets"] = prismMesh->getNumTetrahedra();
670  state.counters["Iterations"] = state.range(1);
671 
672  // This loop gets timed
673  for (auto _ : state)
674  {
675  scene->advance(dt);
676  }
677 }
678 
679 BENCHMARK(BM_PbdContactDistanceVol)
680 ->Unit(benchmark::kMillisecond)
681 ->Name("Distance and Volume Constraints with Contact: Tet Mesh")
682 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
683 
687 static void
688 BM_PbdContactDistanceDihedral(benchmark::State& state)
689 {
690  // Setup
691  auto scene = std::make_shared<Scene>("PbdBenchmark");
692  double dt = 0.05;
693 
694  auto prismObj = std::make_shared<PbdObject>("Prism");
695 
696  // Setup the Geometry
697  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
698  Vec3d(4.0, 4.0, 4.0),
699  Vec3i(state.range(0), state.range(0), state.range(0)),
700  Vec3d(0.0, 0.0, 0.0));
701 
702  // Create surface mesh for contact
703  std::shared_ptr<SurfaceMesh> surfMesh = prismMesh->extractSurfaceMesh();
704 
705  // Use surface mesh for collision
706  prismObj->setCollidingGeometry(surfMesh);
707 
708  // Setup the Parameters
709  auto pbdParams = std::make_shared<PbdModelConfig>();
710  // Set up distance+dihearal angle constraints
711  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Dihedral, 0.9);
712  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 0.9);
713  pbdParams->m_doPartitioning = false;
714  pbdParams->m_gravity = Vec3d(0.0, -2.0 / (double)state.range(0), 0.0);
715  pbdParams->m_dt = dt;
716  pbdParams->m_iterations = state.range(1);
717  pbdParams->m_linearDampingCoeff = 0.03;
718 
719  // Setup the Model
720  auto pbdModel = std::make_shared<PbdModel>();
721  pbdModel->configure(pbdParams);
722 
723  // Setup the Object
724  prismObj->setPhysicsGeometry(surfMesh);
725  prismObj->setDynamicalModel(pbdModel);
726  prismObj->getPbdBody()->uniformMassValue = 0.05;
727  // Fix the borders
728  for (int vert_id = 0; vert_id < surfMesh->getNumVertices(); vert_id++)
729  {
730  auto position = surfMesh->getVertexPosition(vert_id);
731 
732  // Switch to Eigen.isApprox()
733  if (position.y() == 2.0)
734  {
735  prismObj->getPbdBody()->fixedNodeIds.push_back(vert_id);
736  }
737  }
738 
739  // Add Capsule for collision
740  auto capsule = std::make_shared<Capsule>();
741  capsule->setRadius(0.5);
742  capsule->setLength(2);
743  capsule->setPosition(Vec3d(0.0, -2.6, 0.0));
744  capsule->setOrientation(Quatd(0.707, 0.0, 0.0, 0.707));
745 
746  // Set up collision
747  std::shared_ptr<CollidingObject> collisionObj = std::make_shared<CollidingObject>("CollidingObject");
748  collisionObj->setCollidingGeometry(capsule);
749  collisionObj->setVisualGeometry(capsule);
750  scene->addSceneObject(collisionObj);
751 
752  std::shared_ptr<PbdObjectCollision> pbdInteraction =
753  std::make_shared<PbdObjectCollision>(prismObj, collisionObj, "SurfaceMeshToCapsuleCD");
754  pbdInteraction->setFriction(0.0);
755  pbdInteraction->setRestitution(0.0);
756 
757  scene->addInteraction(pbdInteraction);
758 
759  scene->addSceneObject(prismObj);
760  scene->initialize();
761 
762  // Setup outputs for results
763  state.counters["DOFs"] = surfMesh->getNumVertices();
764  state.counters["Tris"] = surfMesh->getNumTriangles();
765  state.counters["Iterations"] = state.range(1);
766 
767  // Note: Do this for other cases: call 4-5
768  // scene->advance(dt);
769 
770  // This loop gets timed
771  for (auto _ : state)
772  {
773  scene->advance(dt);
774  }
775 }
776 
777 BENCHMARK(BM_PbdContactDistanceDihedral)
778 ->Unit(benchmark::kMillisecond)
779 ->Name("Distance and Dihedral Angle Constraints with Contact: Surface Mesh")
780 ->ArgsProduct({ { 4, 8, 10, 16, 26, 38 }, { 2, 5, 8 } });
781 //->ArgsProduct({{4,6,8,10,16,20}, {2, 5, 8}});
782 
786 static void
787 BM_PbdFemContact(benchmark::State& state)
788 {
789  // Setup simulation
790  auto scene = std::make_shared<Scene>("PbdBenchmark");
791 
792  double dt = 0.05;
793 
794  // Create PBD object
795  auto prismObj = std::make_shared<PbdObject>("Prism");
796 
797  // Setup the Geometry
798  std::shared_ptr<TetrahedralMesh> prismMesh = makeTetGrid(
799  Vec3d(4.0, 4.0, 4.0),
800  Vec3i(state.range(0), state.range(0), state.range(0)),
801  Vec3d(0.0, 0.0, 0.0));
802 
803  // Create surface mesh for contact
804  std::shared_ptr<SurfaceMesh> surfMesh = prismMesh->extractSurfaceMesh();
805 
806  // Use surface mesh for collision
807  prismObj->setCollidingGeometry(surfMesh);
808 
809  // Force deformation to match between the surface and volume mesh
810  prismObj->setPhysicsToCollidingMap(std::make_shared<PointwiseMap>(prismMesh, surfMesh));
811 
812  // Setup the Parameters
813  auto pbdParams = std::make_shared<PbdModelConfig>();
814  // Use FEMTet constraints
815  pbdParams->m_femParams->m_YoungModulus = 5.0;
816  pbdParams->m_femParams->m_PoissonRatio = 0.4;
817  pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::StVK);
818  pbdParams->m_doPartitioning = false;
819  pbdParams->m_gravity = Vec3d(0.0, -1.0, 0.0);
820  pbdParams->m_dt = dt;
821  pbdParams->m_iterations = state.range(1);
822  pbdParams->m_linearDampingCoeff = 0.03;
823 
824  // Setup the Model
825  auto pbdModel = std::make_shared<PbdModel>();
826  pbdModel->configure(pbdParams);
827 
828  // Setup the Object
829  prismObj->setPhysicsGeometry(prismMesh);
830  prismObj->setDynamicalModel(pbdModel);
831  prismObj->getPbdBody()->uniformMassValue = 0.05;
832  // Fix the borders
833  for (int z = 0; z < state.range(0); z++)
834  {
835  for (int y = 0; y < state.range(0); y++)
836  {
837  for (int x = 0; x < state.range(0); x++)
838  {
839  if (y == state.range(0) - 1)
840  {
841  prismObj->getPbdBody()->fixedNodeIds.push_back(x + state.range(0) * (y + state.range(0) * z));
842  }
843  }
844  }
845  }
846 
847  // Add Capsule for collision
848  auto capsule = std::make_shared<Capsule>();
849  capsule->setRadius(0.5);
850  capsule->setLength(2);
851  capsule->setPosition(Vec3d(0.0, -2.6, 0.0));
852  capsule->setOrientation(Quatd(0.707, 0.0, 0.0, 0.707));
853 
854  // Set up collision
855  std::shared_ptr<CollidingObject> collisionObj = std::make_shared<CollidingObject>("CollidingObject");
856  collisionObj->setCollidingGeometry(capsule);
857  collisionObj->setVisualGeometry(capsule);
858  scene->addSceneObject(collisionObj);
859 
860  std::shared_ptr<PbdObjectCollision> pbdInteraction =
861  std::make_shared<PbdObjectCollision>(prismObj, collisionObj, "SurfaceMeshToCapsuleCD");
862  pbdInteraction->setFriction(0.0);
863  pbdInteraction->setRestitution(0.0);
864 
865  scene->addInteraction(pbdInteraction);
866 
867  // Create the scene
868  scene->addSceneObject(prismObj);
869  scene->initialize();
870 
871  // Setup outputs for results
872  state.counters["DOFs"] = prismMesh->getNumVertices();
873  state.counters["Tets"] = prismMesh->getNumTetrahedra();
874  state.counters["Iterations"] = state.range(1);
875 
876  // This loop gets timed
877  for (auto _ : state)
878  {
879  scene->advance(dt);
880  }
881 }
882 
883 BENCHMARK(BM_PbdFemContact)
884 ->Unit(benchmark::kMillisecond)
885 ->Name("FEM Constraints with contact: Tet Mesh")
886 ->ArgsProduct({ { 4, 6, 8, 10, 16, 20 }, { 2, 5, 8 } });
887 
888 // Run the benchmark
889 BENCHMARK_MAIN();
Compound Geometry.
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
VecDataArray< U, N > cast()
Templated copy the current array with a new internal data type, does not change the number of compone...