iMSTK
Interactive Medical Simulation Toolkit
imstkPbdModelConfig.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 "imstkPbdModel.h"
8 #include "imstkGraph.h"
9 #include "imstkLineMesh.h"
10 #include "imstkLogger.h"
11 #include "imstkParallelUtils.h"
12 #include "imstkPbdConstraintFunctor.h"
13 #include "imstkPbdModelConfig.h"
14 #include "imstkPbdSolver.h"
15 #include "imstkTaskGraph.h"
16 
17 #include <algorithm>
18 
19 namespace
20 {
21 template<class FunctorType>
22 void
23 eraseOldFunctor(std::vector<std::shared_ptr<imstk::PbdConstraintFunctor>>& funcs, int bodyId)
24 {
25  // Find and erase the functor with the same bodyId
26  funcs.erase(std::remove_if(funcs.begin(), funcs.end(), [bodyId](auto item) {
27  if (FunctorType* functor = dynamic_cast<FunctorType*>(item.get()))
28  {
29  return functor->m_bodyIndex == bodyId;
30  }
31  return false;
32  }), funcs.end());
33 }
34 } // namespace
35 
36 namespace imstk
37 {
38 void
40 {
41  if (std::abs(m_femParams->m_mu) < std::numeric_limits<double>::min()
42  && std::abs(m_femParams->m_lambda) < std::numeric_limits<double>::min())
43  {
44  const double E = m_femParams->m_YoungModulus;
45  const double nu = m_femParams->m_PoissonRatio;
46  m_femParams->m_mu = E / 2.0 / (1.0 + nu);
47  m_femParams->m_lambda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu));
48  }
49  else
50  {
51  const double mu = m_femParams->m_mu;
52  const double lambda = m_femParams->m_lambda;
53  m_femParams->m_YoungModulus = mu * (3.0 * lambda + 2.0 * mu) / (lambda + mu);
54  m_femParams->m_PoissonRatio = lambda / 2.0 / (lambda + mu);
55  }
56 }
57 
58 void
59 PbdModelConfig::enableConstraint(ConstraintGenType type, double stiffness, const int bodyId)
60 {
61  auto& funcs = m_functors[type];
62 
63  eraseOldFunctor<PbdBodyConstraintFunctor>(funcs, bodyId);
64 
65  if (type == ConstraintGenType::Distance)
66  {
67  auto functor = std::make_shared<PbdDistanceConstraintFunctor>();
68  funcs.push_back(functor);
69  functor->setStiffness(stiffness);
70  functor->setBodyIndex(bodyId);
71  }
72  else if (type == ConstraintGenType::Volume)
73  {
74  auto functor = std::make_shared<PbdVolumeConstraintFunctor>();
75  funcs.push_back(functor);
76  functor->setStiffness(stiffness);
77  functor->setBodyIndex(bodyId);
78  }
79  else if (type == ConstraintGenType::Area)
80  {
81  auto functor = std::make_shared<PbdAreaConstraintFunctor>();
82  funcs.push_back(functor);
83  functor->setStiffness(stiffness);
84  functor->setBodyIndex(bodyId);
85  }
86  else if (type == ConstraintGenType::Bend)
87  {
88  auto functor = std::make_shared<PbdBendConstraintFunctor>();
89  funcs.push_back(functor);
90  functor->setStiffness(stiffness);
91  functor->setStride(1);
92  functor->setBodyIndex(bodyId);
93  }
94  else if (type == ConstraintGenType::Dihedral)
95  {
96  auto functor = std::make_shared<PbdDihedralConstraintFunctor>();
97  funcs.push_back(functor);
98  functor->setStiffness(stiffness);
99  functor->setBodyIndex(bodyId);
100  }
101  else if (type == ConstraintGenType::ConstantDensity)
102  {
103  auto functor = std::make_shared<PbdConstantDensityConstraintFunctor>();
104  funcs.push_back(functor);
105  functor->setStiffness(stiffness);
106  functor->setBodyIndex(bodyId);
107  }
108  else
109  {
110  LOG(FATAL) << "There exists no standard constraint functor for the ConstraintGenType";
111  }
112 }
113 
114 void
115 PbdModelConfig::enableDistanceConstraint(const double stiffness, const double stretch, const int bodyId)
116 {
117  auto& funcs = m_functors[ConstraintGenType::Distance];
118 
119  eraseOldFunctor<PbdBodyConstraintFunctor>(funcs, bodyId);
120 
121  auto functor = std::make_shared<PbdDistanceConstraintFunctor>();
122  funcs.push_back(functor);
123  functor->setStiffness(stiffness);
124  functor->setStretch(stretch);
125  functor->setBodyIndex(bodyId);
126 }
127 
128 void
129 PbdModelConfig::enableBendConstraint(const double stiffness, const int stride, const bool restLength0, const int bodyId)
130 {
131  using FunctorType = PbdBendConstraintFunctor;
132  auto& funcs = m_functors[ConstraintGenType::Bend];
133 
134  // Find and remove the functor with the same bodyId and stride
135  funcs.erase(std::remove_if(funcs.begin(), funcs.end(), [bodyId, stride](auto item) {
136  if (FunctorType* functor = dynamic_cast<FunctorType*>(item.get()))
137  {
138  return functor->m_bodyIndex == bodyId && functor->getStride() == stride;
139  }
140  return false;
141  }), funcs.end());
142 
143  auto functor = std::make_shared<FunctorType>();
144 
145  functor->setRestLength(restLength0 ? 0.0 : -1.0);
146  functor->setBodyIndex(bodyId);
147  functor->setStiffness(stiffness);
148  functor->setStride(stride);
149  funcs.push_back(functor);
150 }
151 
152 void
154  const double particleRadius, const double restDensity, const int bodyId)
155 {
156  using FunctorType = PbdConstantDensityConstraintFunctor;
157  auto& funcs = m_functors[ConstraintGenType::ConstantDensity];
158 
159  eraseOldFunctor<FunctorType>(funcs, bodyId);
160 
161  auto functor = std::make_shared<FunctorType>();
162 
163  functor->setParticleRadius(particleRadius);
164  functor->setBodyIndex(bodyId);
165  functor->setStiffness(stiffness);
166  functor->setRestDensity(restDensity);
167 
168  funcs.push_back(std::move(functor));
169 }
170 
171 void
172 PbdModelConfig::enableFemConstraint(PbdFemConstraint::MaterialType material, const int bodyId)
173 {
174  using FunctorType = PbdFemTetConstraintFunctor;
175  auto& funcs = m_functors[ConstraintGenType::FemTet];
176 
177  eraseOldFunctor<FunctorType>(funcs, bodyId);
178 
179  auto functor = std::make_shared<FunctorType>();
180 
181  functor->setBodyIndex(bodyId);
182  functor->setFemConfig(m_femParams);
183  functor->setMaterialType(material);
184 
185  funcs.push_back(std::move(functor));
186 }
187 
188 void
189 PbdModelConfig::enableFemConstraint(PbdFemConstraint::MaterialType material, double youngsModulus, double poisson, const int bodyId)
190 {
191  using FunctorType = PbdFemTetConstraintFunctor;
192  auto& funcs = m_functors[ConstraintGenType::FemTet];
193 
194  eraseOldFunctor<FunctorType>(funcs, bodyId);
195 
196  auto functor = std::make_shared<FunctorType>();
197 
198  auto params = std::make_shared<PbdFemConstraintConfig>();
199  params->setYoungAndPoisson(youngsModulus, poisson);
200 
201  functor->setBodyIndex(bodyId);
202  functor->setFemConfig(params);
203  functor->setMaterialType(material);
204 
205  funcs.push_back(std::move(functor));
206 }
207 
208 void
210  const double linearDampCoeff, const double angularDampCoeff)
211 {
212  m_bodyLinearDampingCoeff[bodyId] = linearDampCoeff;
213  m_bodyAngularDampingCoeff[bodyId] = angularDampCoeff;
214 }
215 
216 double
218 {
219  const double dampMult = (1.0 - m_linearDampingCoeff);
220  auto iter = m_bodyLinearDampingCoeff.find(bodyId);
221  if (iter != m_bodyLinearDampingCoeff.end())
222  {
223  const double bodyDampMult = (1.0 - iter->second);
224  return 1.0 - (dampMult * bodyDampMult);
225  }
226  else
227  {
228  return m_linearDampingCoeff;
229  }
230 }
231 
232 double
233 PbdModelConfig::getAngularDamping(const int bodyId)
234 {
235  const double dampMult = (1.0 - m_angularDampingCoeff);
236  auto iter = m_bodyAngularDampingCoeff.find(bodyId);
237  if (iter != m_bodyAngularDampingCoeff.end())
238  {
239  const double bodyDampMult = (1.0 - iter->second);
240  return 1.0 - (dampMult * bodyDampMult);
241  }
242  else
243  {
244  return m_angularDampingCoeff;
245  }
246 }
247 } // namespace imstk
double m_linearDampingCoeff
Damping coefficient applied to linear velocity [0, 1].
PbdBendConstraintFunctor generates constraints per cell of a LineMesh.
void enableFemConstraint(PbdFemConstraint::MaterialType material, const int bodyId=2)
Enable a Fem constraint with the material provided.
void computeElasticConstants()
If lame parameters (mu+lambda) are given in femParams, then youngs modulus and poissons ratio are com...
double m_angularDampingCoeff
Damping coefficient applied to angular velcoity [0, 1].
void enableBendConstraint(const double stiffness, const int stride, const bool restLength0=true, const int bodyId=2)
Enables a bend constraint with given stiffness, stride, and flag for 0 rest length You may enable mul...
double getLinearDamping(const int bodyId)
Returns global and per body damping multiplied together for a body 1.0 is fully damped/all velocity r...
Compound Geometry.
void enableConstraint(ConstraintGenType type, const double stiffness, const int bodyId=2)
Enables a constraint of type defined by ConstraintGenType with given stiffness. If constraint of that...
void setBodyDamping(const int bodyId, const double linearDampCoeff, const double angularDampCoeff=0.01)
Set damping for a specific body 1.0 is fully damped/all velocity removed, 0.0 is no damping...
void enableConstantDensityConstraint(const double stiffness, const double particleRadius, const double restDensity=6378.0, const int bodyId=2)
Enables constant density constraint given the stiffness and particleSize.
PbdFemTetConstraintFunctor generates constraints per cell of a TetrahedralMesh.
ConstraintGenType
Gives the set of standard pbd constraint generation schemes/functors provided by iMSTK. Note, these do not correspond to constraint types as there may be multiple schemes for one constraint or even multiple constraints per scheme.
PbdConstantDensityConstraintFunctor generates a global constant density constraint for an entire Poin...
std::unordered_map< int, double > m_bodyAngularDampingCoeff
Per body angular damping, Body id -> angular damping for given body [0, 1].
std::unordered_map< int, double > m_bodyLinearDampingCoeff
Per body linear damping, Body id -> linear damping for given body [0, 1].
void enableDistanceConstraint(const double stiffness, const double stretch, const int bodyId)
Enables a Distance constraint on the body Will remove an existing distance constraint on the same bod...