add damping energy in line search

This commit is contained in:
Xuchen Han
2019-09-17 14:58:16 -07:00
parent 3dcfcda19a
commit ae42cc561e
15 changed files with 128 additions and 74 deletions

View File

@@ -50,7 +50,8 @@ public:
A.precondition(r, z); A.precondition(r, z);
A.project(z); A.project(z);
btScalar r_dot_z = dot(z,r); btScalar r_dot_z = dot(z,r);
btScalar local_tolerance = btMin(relative_tolerance * std::sqrt(r_dot_z), tolerance); // btScalar local_tolerance = btMin(relative_tolerance * std::sqrt(r_dot_z), tolerance);
btScalar local_tolerance = tolerance;
if (std::sqrt(r_dot_z) <= local_tolerance) { if (std::sqrt(r_dot_z) <= local_tolerance) {
if (verbose) if (verbose)
{ {
@@ -66,7 +67,7 @@ public:
A.multiply(p, temp); A.multiply(p, temp);
A.project(temp); A.project(temp);
// alpha = r^T * z / (p^T * A * p) // alpha = r^T * z / (p^T * A * p)
if (dot(p,temp) < 0) if (dot(p,temp) < SIMD_EPSILON)
{ {
if (verbose) if (verbose)
std::cout << "Encountered negative direction in CG!"<<std::endl; std::cout << "Encountered negative direction in CG!"<<std::endl;
@@ -92,6 +93,7 @@ public:
} }
return k; return k;
} }
btScalar beta = r_dot_z_new/r_dot_z; btScalar beta = r_dot_z_new/r_dot_z;
p = multAndAdd(beta, p, z); p = multAndAdd(beta, p, z);
} }

View File

@@ -19,7 +19,7 @@
btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v) btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v)
: m_softBodies(softBodies) : m_softBodies(softBodies)
, projection(m_softBodies, m_dt) , m_projection(softBodies)
, m_backupVelocity(backup_v) , m_backupVelocity(backup_v)
, m_implicit(false) , m_implicit(false)
{ {
@@ -46,8 +46,7 @@ void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar
{ {
m_lf[i]->reinitialize(nodeUpdated); m_lf[i]->reinitialize(nodeUpdated);
} }
projection.reinitialize(nodeUpdated); m_projection.reinitialize(nodeUpdated);
projection.setIndices(getIndices());
m_preconditioner->reinitialize(nodeUpdated); m_preconditioner->reinitialize(nodeUpdated);
} }
@@ -85,13 +84,6 @@ void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b)
void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv) void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
{ {
// // only the velocity of the constrained nodes needs to be updated during contact solve
// for (int i = 0; i < projection.m_constraints.size(); ++i)
// {
// int index = projection.m_constraints.getKeyAtIndex(i).getUid1();
// m_nodes[index]->m_v = m_backupVelocity[index] + dv[index];
// }
for (int i = 0; i < m_softBodies.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody* psb = m_softBodies[i]; btSoftBody* psb = m_softBodies[i];
@@ -137,7 +129,7 @@ void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack &r
m_lf[i]->addScaledDampingForce(dt, residual); m_lf[i]->addScaledDampingForce(dt, residual);
} }
} }
projection.project(residual); m_projection.project(residual);
} }
btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
@@ -150,12 +142,12 @@ btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual
return std::sqrt(mag); return std::sqrt(mag);
} }
btScalar btDeformableBackwardEulerObjective::totalEnergy() btScalar btDeformableBackwardEulerObjective::totalEnergy(btScalar dt)
{ {
btScalar e = 0; btScalar e = 0;
for (int i = 0; i < m_lf.size(); ++i) for (int i = 0; i < m_lf.size(); ++i)
{ {
e += m_lf[i]->totalElasticEnergy(); e += m_lf[i]->totalEnergy(dt);
} }
return e; return e;
} }
@@ -164,7 +156,7 @@ void btDeformableBackwardEulerObjective::applyExplicitForce(TVStack& force)
{ {
for (int i = 0; i < m_softBodies.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
m_softBodies[i]->updateDeformation(); m_softBodies[i]->advanceDeformation();
} }
for (int i = 0; i < m_lf.size(); ++i) for (int i = 0; i < m_lf.size(); ++i)
@@ -191,10 +183,10 @@ void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack
//set constraints as projections //set constraints as projections
void btDeformableBackwardEulerObjective::setConstraints() void btDeformableBackwardEulerObjective::setConstraints()
{ {
projection.setConstraints(); m_projection.setConstraints();
} }
void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r) void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
{ {
projection.applyDynamicFriction(r); m_projection.applyDynamicFriction(r);
} }

View File

@@ -34,7 +34,7 @@ public:
btAlignedObjectArray<btDeformableLagrangianForce*> m_lf; btAlignedObjectArray<btDeformableLagrangianForce*> m_lf;
btAlignedObjectArray<btSoftBody *>& m_softBodies; btAlignedObjectArray<btSoftBody *>& m_softBodies;
Preconditioner* m_preconditioner; Preconditioner* m_preconditioner;
btDeformableContactProjection projection; btDeformableContactProjection m_projection;
const TVStack& m_backupVelocity; const TVStack& m_backupVelocity;
btAlignedObjectArray<btSoftBody::Node* > m_nodes; btAlignedObjectArray<btSoftBody::Node* > m_nodes;
bool m_implicit; bool m_implicit;
@@ -71,6 +71,7 @@ public:
void setDt(btScalar dt); void setDt(btScalar dt);
// add friction force to residual
void applyDynamicFriction(TVStack& r); void applyDynamicFriction(TVStack& r);
// add dv to velocity // add dv to velocity
@@ -83,7 +84,7 @@ public:
void project(TVStack& r) void project(TVStack& r)
{ {
BT_PROFILE("project"); BT_PROFILE("project");
projection.project(r); m_projection.project(r);
} }
// perform precondition M^(-1) x = b // perform precondition M^(-1) x = b
@@ -124,7 +125,7 @@ public:
m_implicit = implicit; m_implicit = implicit;
} }
btScalar totalEnergy(); btScalar totalEnergy(btScalar dt);
}; };
#endif /* btBackwardEulerObjective_h */ #endif /* btBackwardEulerObjective_h */

View File

@@ -22,11 +22,11 @@
btDeformableBodySolver::btDeformableBodySolver() btDeformableBodySolver::btDeformableBodySolver()
: m_numNodes(0) : m_numNodes(0)
, m_cg(20) , m_cg(20)
, m_maxNewtonIterations(10) , m_maxNewtonIterations(3)
, m_newtonTolerance(1e-4) , m_newtonTolerance(1e-4)
, m_lineSearch(true) , m_lineSearch(true)
{ {
m_objective = new btDeformableBackwardEulerObjective(m_softBodySet, m_backupVelocity); m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
} }
btDeformableBodySolver::~btDeformableBodySolver() btDeformableBodySolver::~btDeformableBodySolver()
@@ -51,9 +51,9 @@ void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
updateState(); updateState();
// add the inertia term in the residual // add the inertia term in the residual
int counter = 0; int counter = 0;
for (int k = 0; k < m_softBodySet.size(); ++k) for (int k = 0; k < m_softBodies.size(); ++k)
{ {
btSoftBody* psb = m_softBodySet[k]; btSoftBody* psb = m_softBodies[k];
for (int j = 0; j < psb->m_nodes.size(); ++j) for (int j = 0; j < psb->m_nodes.size(); ++j)
{ {
if (psb->m_nodes[j].m_im > 0) if (psb->m_nodes[j].m_im > 0)
@@ -77,7 +77,7 @@ void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
btScalar alpha = 0.01, beta = 0.5; // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8 btScalar alpha = 0.01, beta = 0.5; // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8
btScalar scale = 2; btScalar scale = 2;
// todo xuchenhan@: add damping energy to f0 and f1 // todo xuchenhan@: add damping energy to f0 and f1
btScalar f0 = m_objective->totalEnergy()+kineticEnergy(), f1, f2; btScalar f0 = m_objective->totalEnergy(solverdt)+kineticEnergy(), f1, f2;
backupDv(); backupDv();
do { do {
scale *= beta; scale *= beta;
@@ -85,9 +85,9 @@ void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
return; return;
} }
updateEnergy(scale); updateEnergy(scale);
f1 = m_objective->totalEnergy()+kineticEnergy(); f1 = m_objective->totalEnergy(solverdt)+kineticEnergy();
f2 = f0 - alpha * scale * inner_product; f2 = f0 - alpha * scale * inner_product;
} while (!(f1 < f2+SIMD_EPSILON)); // if anything here is nan then the search continues } while (!(f1 < f2)); // if anything here is nan then the search continues
revertDv(); revertDv();
updateDv(scale); updateDv(scale);
} }
@@ -108,9 +108,9 @@ void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
btScalar btDeformableBodySolver::kineticEnergy() btScalar btDeformableBodySolver::kineticEnergy()
{ {
btScalar ke = 0; btScalar ke = 0;
for (int i = 0; i < m_softBodySet.size();++i) for (int i = 0; i < m_softBodies.size();++i)
{ {
btSoftBody* psb = m_softBodySet[i]; btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size();++j) for (int j = 0; j < psb->m_nodes.size();++j)
{ {
btSoftBody::Node& node = psb->m_nodes[j]; btSoftBody::Node& node = psb->m_nodes[j];
@@ -152,11 +152,13 @@ void btDeformableBodySolver::updateEnergy(btScalar scale)
btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual) btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual)
{ {
btScalar relative_tolerance = btMin(btScalar(0.5), std::sqrt(btMax(m_objective->computeNorm(residual), m_newtonTolerance))); // btScalar relative_tolerance = btMin(btScalar(0.5), std::sqrt(btMax(m_objective->computeNorm(residual), m_newtonTolerance)));
btScalar relative_tolerance = 0.5;
m_cg.solve(*m_objective, ddv, residual, relative_tolerance, false); m_cg.solve(*m_objective, ddv, residual, relative_tolerance, false);
btScalar inner_product = m_cg.dot(residual, m_ddv); btScalar inner_product = m_cg.dot(residual, m_ddv);
btScalar tol = 1e-3 * m_objective->computeNorm(residual) * m_objective->computeNorm(m_ddv);
btScalar res_norm = m_objective->computeNorm(residual); btScalar res_norm = m_objective->computeNorm(residual);
btScalar tol = 1e-5 * res_norm * m_objective->computeNorm(m_ddv);
if (inner_product < -tol) if (inner_product < -tol)
{ {
std::cout << "Looking backwards!" << std::endl; std::cout << "Looking backwards!" << std::endl;
@@ -196,13 +198,14 @@ void btDeformableBodySolver::updateDv(btScalar scale)
void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual) void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
{ {
//btScalar tolerance = std::numeric_limits<btScalar>::epsilon() * m_objective->computeNorm(residual); //btScalar tolerance = std::numeric_limits<btScalar>::epsilon() * m_objective->computeNorm(residual);
btScalar relative_tolerance = btMin(btScalar(0.5), std::sqrt(btMax(m_objective->computeNorm(residual), m_newtonTolerance))); // btScalar relative_tolerance = btMin(btScalar(0.5), std::sqrt(btMax(m_objective->computeNorm(residual), m_newtonTolerance)));
btScalar relative_tolerance = 0.5;
m_cg.solve(*m_objective, ddv, residual, relative_tolerance, false); m_cg.solve(*m_objective, ddv, residual, relative_tolerance, false);
} }
void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt) void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody *>& softBodies, btScalar dt)
{ {
m_softBodySet.copyFromArray(softBodies); m_softBodies.copyFromArray(softBodies);
bool nodeUpdated = updateNodes(); bool nodeUpdated = updateNodes();
if (nodeUpdated) if (nodeUpdated)
@@ -234,7 +237,7 @@ void btDeformableBodySolver::setConstraints()
btScalar btDeformableBodySolver::solveContactConstraints() btScalar btDeformableBodySolver::solveContactConstraints()
{ {
BT_PROFILE("setConstraint"); BT_PROFILE("setConstraint");
btScalar maxSquaredResidual = m_objective->projection.update(); btScalar maxSquaredResidual = m_objective->m_projection.update();
return maxSquaredResidual; return maxSquaredResidual;
} }
@@ -242,9 +245,9 @@ btScalar btDeformableBodySolver::solveContactConstraints()
void btDeformableBodySolver::updateVelocity() void btDeformableBodySolver::updateVelocity()
{ {
int counter = 0; int counter = 0;
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody* psb = m_softBodySet[i]; btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j) for (int j = 0; j < psb->m_nodes.size(); ++j)
{ {
// set NaN to zero; // set NaN to zero;
@@ -261,9 +264,9 @@ void btDeformableBodySolver::updateVelocity()
void btDeformableBodySolver::updateTempPosition() void btDeformableBodySolver::updateTempPosition()
{ {
int counter = 0; int counter = 0;
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody* psb = m_softBodySet[i]; btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j) for (int j = 0; j < psb->m_nodes.size(); ++j)
{ {
psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * psb->m_nodes[j].m_v; psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * psb->m_nodes[j].m_v;
@@ -276,9 +279,9 @@ void btDeformableBodySolver::updateTempPosition()
void btDeformableBodySolver::backupVelocity() void btDeformableBodySolver::backupVelocity()
{ {
int counter = 0; int counter = 0;
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody* psb = m_softBodySet[i]; btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j) for (int j = 0; j < psb->m_nodes.size(); ++j)
{ {
m_backupVelocity[counter++] = psb->m_nodes[j].m_v; m_backupVelocity[counter++] = psb->m_nodes[j].m_v;
@@ -289,9 +292,9 @@ void btDeformableBodySolver::backupVelocity()
void btDeformableBodySolver::setupDeformableSolve(bool implicit) void btDeformableBodySolver::setupDeformableSolve(bool implicit)
{ {
int counter = 0; int counter = 0;
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody* psb = m_softBodySet[i]; btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j) for (int j = 0; j < psb->m_nodes.size(); ++j)
{ {
if (implicit) if (implicit)
@@ -307,9 +310,9 @@ void btDeformableBodySolver::setupDeformableSolve(bool implicit)
void btDeformableBodySolver::revertVelocity() void btDeformableBodySolver::revertVelocity()
{ {
int counter = 0; int counter = 0;
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody* psb = m_softBodySet[i]; btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j) for (int j = 0; j < psb->m_nodes.size(); ++j)
{ {
psb->m_nodes[j].m_v = m_backupVelocity[counter++]; psb->m_nodes[j].m_v = m_backupVelocity[counter++];
@@ -320,8 +323,8 @@ void btDeformableBodySolver::revertVelocity()
bool btDeformableBodySolver::updateNodes() bool btDeformableBodySolver::updateNodes()
{ {
int numNodes = 0; int numNodes = 0;
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
numNodes += m_softBodySet[i]->m_nodes.size(); numNodes += m_softBodies[i]->m_nodes.size();
if (numNodes != m_numNodes) if (numNodes != m_numNodes)
{ {
m_numNodes = numNodes; m_numNodes = numNodes;
@@ -333,9 +336,9 @@ bool btDeformableBodySolver::updateNodes()
void btDeformableBodySolver::predictMotion(btScalar solverdt) void btDeformableBodySolver::predictMotion(btScalar solverdt)
{ {
for (int i = 0; i < m_softBodySet.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
{ {
btSoftBody *psb = m_softBodySet[i]; btSoftBody *psb = m_softBodies[i];
if (psb->isActive()) if (psb->isActive())
{ {
@@ -417,9 +420,9 @@ void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar d
void btDeformableBodySolver::updateSoftBodies() void btDeformableBodySolver::updateSoftBodies()
{ {
for (int i = 0; i < m_softBodySet.size(); i++) for (int i = 0; i < m_softBodies.size(); i++)
{ {
btSoftBody *psb = (btSoftBody *)m_softBodySet[i]; btSoftBody *psb = (btSoftBody *)m_softBodies[i];
if (psb->isActive()) if (psb->isActive())
{ {
psb->updateNormals(); // normal is updated here psb->updateNormals(); // normal is updated here

View File

@@ -37,7 +37,7 @@ protected:
TVStack m_backup_dv; TVStack m_backup_dv;
TVStack m_ddv; TVStack m_ddv;
TVStack m_residual; TVStack m_residual;
btAlignedObjectArray<btSoftBody *> m_softBodySet; btAlignedObjectArray<btSoftBody *> m_softBodies;
btAlignedObjectArray<btVector3> m_backupVelocity; btAlignedObjectArray<btVector3> m_backupVelocity;
btScalar m_dt; btScalar m_dt;

View File

@@ -40,7 +40,6 @@ btScalar btDeformableContactProjection::update()
residualSquare = btMax(residualSquare, localResidualSquare); residualSquare = btMax(residualSquare, localResidualSquare);
} }
// todo xuchenhan@: deformable/deformable constraints
return residualSquare; return residualSquare;
} }
@@ -401,7 +400,6 @@ void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
void btDeformableContactProjection::reinitialize(bool nodeUpdated) void btDeformableContactProjection::reinitialize(bool nodeUpdated)
{ {
btCGProjection::reinitialize(nodeUpdated);
m_staticConstraints.clear(); m_staticConstraints.clear();
m_nodeRigidConstraints.clear(); m_nodeRigidConstraints.clear();
m_faceRigidConstraints.clear(); m_faceRigidConstraints.clear();

View File

@@ -22,9 +22,14 @@
#include "btDeformableContactConstraint.h" #include "btDeformableContactConstraint.h"
#include "LinearMath/btHashMap.h" #include "LinearMath/btHashMap.h"
#include <vector> #include <vector>
class btDeformableContactProjection : public btCGProjection class btDeformableContactProjection
{ {
public: public:
typedef btAlignedObjectArray<btVector3> TVStack;
typedef btAlignedObjectArray<btAlignedObjectArray<btVector3> > TVArrayStack;
typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > TArrayStack;
btAlignedObjectArray<btSoftBody *>& m_softBodies;
// map from node index to static constraint // map from node index to static constraint
btHashMap<btHashInt, btDeformableStaticConstraint> m_staticConstraints; btHashMap<btHashInt, btDeformableStaticConstraint> m_staticConstraints;
// map from node index to node rigid constraint // map from node index to node rigid constraint
@@ -40,8 +45,8 @@ public:
// map from node index to projection directions // map from node index to projection directions
btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict; btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
btDeformableContactProjection(btAlignedObjectArray<btSoftBody *>& softBodies, const btScalar& dt) btDeformableContactProjection(btAlignedObjectArray<btSoftBody *>& softBodies)
: btCGProjection(softBodies, dt) : m_softBodies(softBodies)
{ {
} }

View File

@@ -73,7 +73,7 @@ public:
return BT_GRAVITY_FORCE; return BT_GRAVITY_FORCE;
} }
virtual double totalElasticEnergy() virtual double totalEnergy(btScalar dt)
{ {
double e = 0; double e = 0;
for (int i = 0; i<m_softBodies.size();++i) for (int i = 0; i<m_softBodies.size();++i)

View File

@@ -28,6 +28,11 @@ enum btDeformableLagrangianForceType
BT_NEOHOOKEAN_FORCE = 4 BT_NEOHOOKEAN_FORCE = 4
}; };
static inline double randomDouble(double low, double high)
{
return low + static_cast<double>(rand()) / RAND_MAX * (high - low);
}
class btDeformableLagrangianForce class btDeformableLagrangianForce
{ {
public: public:
@@ -176,7 +181,7 @@ public:
psb->updateDeformation(); psb->updateDeformation();
} }
counter = 0; counter = 0;
double f1 = totalElasticEnergy(); double f1 = totalElasticEnergy(0);
for (int i = 0; i<m_softBodies.size();++i) for (int i = 0; i<m_softBodies.size();++i)
{ {
@@ -190,7 +195,7 @@ public:
} }
counter = 0; counter = 0;
double f2 = totalElasticEnergy(); double f2 = totalElasticEnergy(0);
//restore m_q //restore m_q
for (int i = 0; i<m_softBodies.size();++i) for (int i = 0; i<m_softBodies.size();++i)
@@ -337,14 +342,22 @@ public:
} }
} }
virtual double totalElasticEnergy() //
virtual double totalElasticEnergy(btScalar dt)
{ {
return 0; return 0;
} }
double randomDouble(double low, double high) //
virtual double totalDampingEnergy(btScalar dt)
{ {
return low + static_cast<double>(rand()) / RAND_MAX * (high - low); return 0;
}
// total Energy takes dt as input because certain energies depend on dt
virtual double totalEnergy(btScalar dt)
{
return totalElasticEnergy(dt) + totalDampingEnergy(dt);
} }
}; };
#endif /* BT_DEFORMABLE_LAGRANGIAN_FORCE */ #endif /* BT_DEFORMABLE_LAGRANGIAN_FORCE */

View File

@@ -129,7 +129,7 @@ public:
} }
} }
} }
virtual double totalElasticEnergy() virtual double totalElasticEnergy(btScalar dt)
{ {
double energy = 0; double energy = 0;
for (int i = 0; i < m_softBodies.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)

View File

@@ -194,7 +194,7 @@ void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
// set up constraints among multibodies and between multibodies and deformable bodies // set up constraints among multibodies and between multibodies and deformable bodies
setupConstraints(); setupConstraints();
solveMultiBodyRelatedConstraints(); solveMultiBodyRelatedConstraints();
m_deformableBodySolver->m_objective->projection.setProjection(); m_deformableBodySolver->m_objective->m_projection.setProjection();
// for explicit scheme, m_backupVelocity = v_{n+1}^* // for explicit scheme, m_backupVelocity = v_{n+1}^*
// for implicit scheme, m_backupVelocity = v_n // for implicit scheme, m_backupVelocity = v_n

View File

@@ -26,12 +26,12 @@ public:
btScalar m_mu_damp, m_lambda_damp; btScalar m_mu_damp, m_lambda_damp;
btDeformableNeoHookeanForce(): m_mu(1), m_lambda(1) btDeformableNeoHookeanForce(): m_mu(1), m_lambda(1)
{ {
btScalar damping = 0.005; btScalar damping = 0.05;
m_mu_damp = damping * m_mu; m_mu_damp = damping * m_mu;
m_lambda_damp = damping * m_lambda; m_lambda_damp = damping * m_lambda;
} }
btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0): m_mu(mu), m_lambda(lambda) btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05): m_mu(mu), m_lambda(lambda)
{ {
m_mu_damp = damping * m_mu; m_mu_damp = damping * m_mu;
m_lambda_damp = damping * m_lambda; m_lambda_damp = damping * m_lambda;
@@ -71,7 +71,7 @@ public:
size_t id3 = node3->index; size_t id3 = node3->index;
btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse; btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
btMatrix3x3 dP; btMatrix3x3 dP;
firstPiolaDampingDifferential(psb->m_tetraScratches[j], dF, dP); firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col); btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose(); btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
@@ -85,7 +85,7 @@ public:
} }
} }
virtual double totalElasticEnergy() virtual double totalElasticEnergy(btScalar dt)
{ {
double energy = 0; double energy = 0;
for (int i = 0; i < m_softBodies.size(); ++i) for (int i = 0; i < m_softBodies.size(); ++i)
@@ -101,6 +101,35 @@ public:
return energy; return energy;
} }
virtual double totalDampingEnergy(btScalar dt)
{
double energy = 0;
int sz = 0;
for (int i = 0; i < m_softBodies.size(); ++i)
{
btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j)
{
sz = btMax(sz, psb->m_nodes[j].index);
}
}
TVStack dampingForce;
dampingForce.resize(sz+1);
for (int i = 0; i < dampingForce.size(); ++i)
dampingForce[i].setZero();
addScaledDampingForce(0.5, dampingForce);
for (int i = 0; i < m_softBodies.size(); ++i)
{
btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j)
{
const btSoftBody::Node& node = psb->m_nodes[j];
energy -= dampingForce[node.index].dot(node.m_v) / dt;
}
}
return energy;
}
double elasticEnergyDensity(const btSoftBody::TetraScratch& s) double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
{ {
double density = 0; double density = 0;
@@ -168,7 +197,7 @@ public:
size_t id3 = node3->index; size_t id3 = node3->index;
btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse; btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
btMatrix3x3 dP; btMatrix3x3 dP;
firstPiolaDampingDifferential(psb->m_tetraScratches[j], dF, dP); firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col); btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose(); btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();

View File

@@ -2914,6 +2914,15 @@ void btSoftBody::updateDeformation()
s.m_cofF = t.m_F.adjoint().transpose(); s.m_cofF = t.m_F.adjoint().transpose();
} }
} }
void btSoftBody::advanceDeformation()
{
updateDeformation();
for (int i = 0; i < m_tetras.size(); ++i)
{
m_tetraScratchesTn[i] = m_tetraScratches[i];
}
}
// //
void btSoftBody::Joint::Prepare(btScalar dt, int) void btSoftBody::Joint::Prepare(btScalar dt, int)
{ {

View File

@@ -770,6 +770,7 @@ public:
tFaceArray m_renderFaces; // Faces tFaceArray m_renderFaces; // Faces
tTetraArray m_tetras; // Tetras tTetraArray m_tetras; // Tetras
btAlignedObjectArray<TetraScratch> m_tetraScratches; btAlignedObjectArray<TetraScratch> m_tetraScratches;
btAlignedObjectArray<TetraScratch> m_tetraScratchesTn;
tAnchorArray m_anchors; // Anchors tAnchorArray m_anchors; // Anchors
tRContactArray m_rcontacts; // Rigid contacts tRContactArray m_rcontacts; // Rigid contacts
btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts; btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts;
@@ -1100,6 +1101,7 @@ public:
void setSpringStiffness(btScalar k); void setSpringStiffness(btScalar k);
void initializeDmInverse(); void initializeDmInverse();
void updateDeformation(); void updateDeformation();
void advanceDeformation();
void applyForces(); void applyForces();
void interpolateRenderMesh(); void interpolateRenderMesh();
static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti); static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti);
@@ -1114,8 +1116,6 @@ public:
///fills the dataBuffer and returns the struct name (and 0 on failure) ///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
//virtual void serializeSingleObject(class btSerializer* serializer) const;
}; };
#endif //_BT_SOFT_BODY_H #endif //_BT_SOFT_BODY_H

View File

@@ -1234,6 +1234,7 @@ if(face&&face[0])
} }
psb->initializeDmInverse(); psb->initializeDmInverse();
psb->m_tetraScratches.resize(psb->m_tetras.size()); psb->m_tetraScratches.resize(psb->m_tetras.size());
psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
printf("Nodes: %u\r\n", psb->m_nodes.size()); printf("Nodes: %u\r\n", psb->m_nodes.size());
printf("Links: %u\r\n", psb->m_links.size()); printf("Links: %u\r\n", psb->m_links.size());
printf("Faces: %u\r\n", psb->m_faces.size()); printf("Faces: %u\r\n", psb->m_faces.size());
@@ -1376,6 +1377,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo,
psb->initializeDmInverse(); psb->initializeDmInverse();
psb->m_tetraScratches.resize(psb->m_tetras.size()); psb->m_tetraScratches.resize(psb->m_tetras.size());
psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
printf("Nodes: %u\r\n", psb->m_nodes.size()); printf("Nodes: %u\r\n", psb->m_nodes.size());
printf("Links: %u\r\n", psb->m_links.size()); printf("Links: %u\r\n", psb->m_links.size());
printf("Faces: %u\r\n", psb->m_faces.size()); printf("Faces: %u\r\n", psb->m_faces.size());