generalize preconditioner, now supports mass preconditioning

This commit is contained in:
Xuchen Han
2019-07-12 10:35:50 -07:00
parent 696c96f392
commit 98cd9a85e4
2 changed files with 75 additions and 17 deletions

View File

@@ -8,14 +8,15 @@
#include "btBackwardEulerObjective.h" #include "btBackwardEulerObjective.h"
btBackwardEulerObjective::btBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v) btBackwardEulerObjective::btBackwardEulerObjective(btAlignedObjectArray<btSoftBody *>& softBodies, const TVStack& backup_v)
: cg(20) : cg(50)
, m_softBodies(softBodies) , m_softBodies(softBodies)
, precondition(DefaultPreconditioner())
, projection(m_softBodies, m_dt) , projection(m_softBodies, m_dt)
, m_backupVelocity(backup_v) , m_backupVelocity(backup_v)
{ {
// TODO: this should really be specified in initialization instead of here // TODO: this should really be specified in initialization instead of here
btMassSpring* mass_spring = new btMassSpring(m_softBodies); btMassSpring* mass_spring = new btMassSpring(m_softBodies);
// m_preconditioner = new MassPreconditioner(m_softBodies);
m_preconditioner = new DefaultPreconditioner();
m_lf.push_back(mass_spring); m_lf.push_back(mass_spring);
} }
@@ -28,8 +29,9 @@ void btBackwardEulerObjective::reinitialize(bool nodeUpdated)
for (int i = 0; i < m_lf.size(); ++i) for (int i = 0; i < m_lf.size(); ++i)
{ {
m_lf[i]->reinitialize(nodeUpdated); m_lf[i]->reinitialize(nodeUpdated);
projection.reinitialize(nodeUpdated);
} }
projection.reinitialize(nodeUpdated);
m_preconditioner->reinitialize(nodeUpdated);
} }
@@ -64,7 +66,7 @@ void btBackwardEulerObjective::multiply(const TVStack& x, TVStack& b) const
void btBackwardEulerObjective::computeStep(TVStack& dv, const TVStack& residual, const btScalar& dt) void btBackwardEulerObjective::computeStep(TVStack& dv, const TVStack& residual, const btScalar& dt)
{ {
m_dt = dt; m_dt = dt;
btScalar tolerance = std::numeric_limits<float>::epsilon()* 16 * computeNorm(residual); btScalar tolerance = std::numeric_limits<float>::epsilon()* 1024 * computeNorm(residual);
cg.solve(*this, dv, residual, tolerance); cg.solve(*this, dv, residual, tolerance);
} }

View File

@@ -15,25 +15,82 @@
#include "btDeformableRigidDynamicsWorld.h" #include "btDeformableRigidDynamicsWorld.h"
class btDeformableRigidDynamicsWorld; class btDeformableRigidDynamicsWorld;
class Preconditioner
{
public:
using TVStack = btAlignedObjectArray<btVector3>;
virtual void operator()(const TVStack& x, TVStack& b) = 0;
virtual void reinitialize(bool nodeUpdated) = 0;
};
class DefaultPreconditioner : public Preconditioner
{
public:
virtual void operator()(const TVStack& x, TVStack& b)
{
btAssert(b.size() == x.size());
for (int i = 0; i < b.size(); ++i)
b[i] = x[i];
}
virtual void reinitialize(bool nodeUpdated)
{
}
};
class MassPreconditioner : public Preconditioner
{
btAlignedObjectArray<btScalar> m_inv_mass;
const btAlignedObjectArray<btSoftBody *>& m_softBodies;
public:
MassPreconditioner(const btAlignedObjectArray<btSoftBody *>& softBodies)
: m_softBodies(softBodies)
{
}
virtual void reinitialize(bool nodeUpdated)
{
if (nodeUpdated)
{
m_inv_mass.clear();
for (int i = 0; i < m_softBodies.size(); ++i)
{
btSoftBody* psb = m_softBodies[i];
for (int j = 0; j < psb->m_nodes.size(); ++j)
m_inv_mass.push_back(psb->m_nodes[j].m_im);
}
}
}
virtual void operator()(const TVStack& x, TVStack& b)
{
btAssert(b.size() == x.size());
btAssert(m_inv_mass.size() == x.size());
for (int i = 0; i < b.size(); ++i)
b[i] = x[i] * m_inv_mass[i];
}
};
class btBackwardEulerObjective class btBackwardEulerObjective
{ {
public: public:
using TVStack = btAlignedObjectArray<btVector3>; using TVStack = btAlignedObjectArray<btVector3>;
struct DefaultPreconditioner // struct DefaultPreconditioner
{ // {
void operator()(const TVStack& x, TVStack& b) // void operator()(const TVStack& x, TVStack& b)
{ // {
btAssert(b.size() == x.size()); // btAssert(b.size() == x.size());
for (int i = 0; i < b.size(); ++i) // for (int i = 0; i < b.size(); ++i)
b[i] = x[i]; // b[i] = x[i];
} // }
}; // };
btScalar m_dt; btScalar m_dt;
btConjugateGradient<btBackwardEulerObjective> cg; btConjugateGradient<btBackwardEulerObjective> cg;
btDeformableRigidDynamicsWorld* m_world; btDeformableRigidDynamicsWorld* m_world;
btAlignedObjectArray<btLagrangianForce*> m_lf; btAlignedObjectArray<btLagrangianForce*> m_lf;
btAlignedObjectArray<btSoftBody *>& m_softBodies; btAlignedObjectArray<btSoftBody *>& m_softBodies;
std::function<void(const TVStack&, TVStack&)> precondition; Preconditioner* m_preconditioner;
btContactProjection projection; btContactProjection projection;
const TVStack& m_backupVelocity; const TVStack& m_backupVelocity;
@@ -92,10 +149,9 @@ public:
projection(r); projection(r);
} }
template <class Func> void precondition(const TVStack& x, TVStack& b)
void setPreconditioner(Func preconditioner_func)
{ {
precondition = preconditioner_func; m_preconditioner->operator()(x,b);
} }
virtual void setWorld(btDeformableRigidDynamicsWorld* world) virtual void setWorld(btDeformableRigidDynamicsWorld* world)