Program Listing for File constraintvolume.cpp#
↰ Return to documentation for file (pymembrane/cppmodule/src/constraints/constraintvolume.cpp
)
#include "constraintvolume.hpp"
#include "../mesh/computegeometry.hpp"
void ConstraintVolume::compute_gradient(void)
{
//Current volume
m_value = 0.0;
//Compute the volume and the sum=G(Q)M^{-1}G(q)
double sum = 0.0;
for (int vertex_index = 0; vertex_index<_system.Numvertices; vertex_index++)
{
int he = _system.vertices[vertex_index]._hedge;
int first = he;
int face_index, he_pair, he_pair_next;
int vf[3];
int v, v1, v2; //index to the vertex which you are calculating the energy/force
double Nx = 0.0, Ny = 0.0, Nz = 0.0;
real3 r, r1, r2;
real3 nt;
do
{
he_pair = _system.halfedges[he].pair;
face_index = _system.halfedges[he_pair].face;
if (face_index != -1)
{
vf[0] = _system.faces[face_index].v1;
vf[1] = _system.faces[face_index].v2;
vf[2] = _system.faces[face_index].v3;
if (vertex_index == vf[0])
{
v = vf[0];
v1 = vf[1];
v2 = vf[2];
}
else if (vertex_index == vf[1])
{
v = vf[1];
v1 = vf[2];
v2 = vf[0];
}
else if (vertex_index == vf[2])
{
v = vf[2];
v1 = vf[0];
v2 = vf[1];
}
//capture the vector positions
r = _system.vertices[v].r;
r1 = _system.vertices[v1].r;
r2 = _system.vertices[v2].r;
//compute the volume in an atomic operation
nt = pymemb::compute_normal_triangle(r, r1, r2);
m_value+= vdot(r, nt) / 6.0 / 3.0;
//compute the volume gradient
Nx += (r1.y * r2.z - r2.y * r1.z);
Ny += (r2.x * r1.z - r1.x * r2.z);
Nz += (r1.x * r2.y - r2.x * r1.y);
}
he_pair_next = _system.halfedges[he_pair].next;
he = he_pair_next;
} while ((he != first));
Nx /= 6.0;
Ny /= 6.0;
Nz /= 6.0;
grad[vertex_index].x = Nx;
grad[vertex_index].y = Ny;
grad[vertex_index].z = Nz;
sum+= Nx * ref_grad[vertex_index].x + Ny * ref_grad[vertex_index].y + Nz * ref_grad[vertex_index].z; //see definition above
}
if (sum > 0.0)
m_lambda = (m_value - m_target) / sum;
else
m_lambda = 0.0;
// std::cout<<"volume:"<<m_value<<" m_lambda:"<<m_lambda<<std::endl;
}
void ConstraintVolume::compute_ref_gradient(void)
{
this->compute_gradient();
ref_grad = grad;
}
void ConstraintVolume::enforce(void)
{
this->compute_ref_gradient();
for (int vertex_index = 0; vertex_index<_system.Numvertices; vertex_index++)
{
_system.vertices[vertex_index].r.x -= m_lambda * ref_grad[vertex_index].x;
_system.vertices[vertex_index].r.y -= m_lambda * ref_grad[vertex_index].y;
_system.vertices[vertex_index].r.z -= m_lambda * ref_grad[vertex_index].z;
// particles may have been moved slightly outside the box by the above steps, wrap them back into place
pymemb::enforce_periodic(_system.vertices[vertex_index].r, _system.vertices[vertex_index].ip, _system.get_box());
}
}