iMSTK
Interactive Medical Simulation Toolkit
imstkPbdSolver.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 "imstkPbdSolver.h"
8 #include "imstkLogger.h"
9 #include "imstkParallelUtils.h"
10 #include "imstkPbdCollisionConstraint.h"
11 #include "imstkPbdConstraintContainer.h"
12 
13 namespace imstk
14 {
15 PbdSolver::PbdSolver() :
16  m_constraints(std::make_shared<PbdConstraintContainer>()),
17  m_constraintLists(std::make_shared<std::list<std::vector<PbdConstraint*>*>>())
18 {
19 }
20 
21 void
22 PbdSolver::solve()
23 {
24  if (m_dataTracker)
25  {
26  m_dataTracker->getStopWatch(DataTracker::ePhysics::SolverTime_ms).start();
27  }
28 
29  size_t numConstraints = 0;
30  const std::vector<std::shared_ptr<PbdConstraint>>& constraints = m_constraints->getConstraints();
31  const std::vector<std::vector<std::shared_ptr<PbdConstraint>>>& partitionedConstraints = m_constraints->getPartitionedConstraints();
32 
33  double averageC = 0.0;
34  double averageLambda = 0.0;
35  numConstraints += constraints.size();
36  // Zero out the Lagrange multiplier
37  for (const auto& constraint : constraints)
38  {
39  constraint->zeroOutLambda();
40  }
41 
42  // Zero out paritioned constraints
43  for (const auto& constraintPartition : partitionedConstraints)
44  {
45  numConstraints += constraints.size();
46  ParallelUtils::parallelFor(constraintPartition.size(),
47  [&](const size_t idx)
48  {
49  constraintPartition[idx]->zeroOutLambda();
50  });
51  }
52 
53  // Zero out insertion/collision constraints
54  for (auto constraintList : *m_constraintLists)
55  {
56  const std::vector<PbdConstraint*>& constraintVec = *constraintList;
57  numConstraints += constraintVec.size();
58  for (size_t j = 0; j < constraintVec.size(); j++)
59  {
60  constraintVec[j]->zeroOutLambda();
61  }
62  }
63 
64  unsigned int i = 0;
65  while (i++ < m_iterations)
66  {
67  // Project collision and all external constraints
68  for (auto constraintList : *m_constraintLists)
69  {
70  const std::vector<PbdConstraint*>& constraintVec = *constraintList;
71  for (size_t j = 0; j < constraintVec.size(); j++)
72  {
73  constraintVec[j]->projectConstraint(*m_state, m_dt, m_solverType);
74  }
75  }
76 
77  // Project all internal body constraints
78  for (const auto& constraint : constraints)
79  {
80  constraint->projectConstraint(*m_state, m_dt, m_solverType);
81  }
82 
83  for (const auto& constraintPartition : partitionedConstraints)
84  {
85  ParallelUtils::parallelFor(constraintPartition.size(),
86  [&](const size_t idx)
87  {
88  constraintPartition[idx]->projectConstraint(*m_state, m_dt, m_solverType);
89  });
91  //for (size_t k = 0; k < constraintPartition.size(); k++)
92  //{
93  // constraintPartition[k]->projectConstraint(invMasses, m_dt, m_solverType, currPositions);
94  //}
95  }
96  }
97 
98  if (m_dataTracker)
99  {
100  m_dataTracker->probeElapsedTime_s(DataTracker::ePhysics::SolverTime_ms);
101  m_dataTracker->probe(DataTracker::ePhysics::NumConstraints, numConstraints);
102 
103  for (const auto& constraint : constraints)
104  {
105  averageC += constraint->getConstraintC();
106  averageLambda += constraint->getLambda();
107  }
108 
109  for (const auto& constraintPartition : partitionedConstraints)
110  {
111  for (size_t k = 0; k < constraintPartition.size(); k++)
112  {
113  averageC += constraintPartition[k]->getConstraintC();
114  averageLambda += constraintPartition[k]->getLambda();
115  }
116  }
117 
118  for (auto constraintList : *m_constraintLists)
119  {
120  const std::vector<PbdConstraint*>& constraintVec = *constraintList;
121  for (size_t j = 0; j < constraintVec.size(); j++)
122  {
123  averageC += constraintVec[j]->getConstraintC();
124  averageLambda += constraintVec[j]->getLambda();
125  }
126  }
127 
128  averageC /= numConstraints;
129  m_dataTracker->probe(DataTracker::ePhysics::AverageC, averageC);
130  }
131 }
132 } // namespace imstk
Compound Geometry.