Program Listing for File constraintarea.cpp#
↰ Return to documentation for file (pymembrane/cppmodule/src/constraints/constraintarea.cpp
)
#include "constraintarea.hpp"
#include "../mesh/computegeometry.hpp"
void ConstraintArea::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];
real Fx = 0.0, Fy = 0.0, Fz = 0.0; // area gradient
real A_T = 0.0;
real g_now[3];
real3 forceM11, forceM12;
real3 r12, r13;
do
{
he_pair = _system.halfedges[he].pair;
face_index = _system.halfedges[he_pair].face;
if (face_index != -1) // Remember -1 is the virtual face outside of the mesh
{
vf[0] = _system.faces[face_index].v1;
vf[1] = _system.faces[face_index].v2;
vf[2] = _system.faces[face_index].v3;
// compute
pymemb::compute_form_factor_triangle(g_now, _system.vertices[vf[0]].r, _system.vertices[vf[1]].r, _system.vertices[vf[2]].r);
vf[2] = _system.faces[face_index].v3;
A_T = pymemb::compute_area_triangle_from_metric(g_now);
m_value += A_T;
r12 = pymemb::vector_subtract(_system.vertices[vf[1]].r, _system.vertices[vf[0]].r);
r13 = pymemb::vector_subtract(_system.vertices[vf[2]].r, _system.vertices[vf[0]].r);
forceM11.x = (0.25 / A_T) * (g_now[2] * r12.x - g_now[1] * r13.x);
forceM11.y = (0.25 / A_T) * (g_now[2] * r12.y - g_now[1] * r13.y);
forceM11.z = (0.25 / A_T) * (g_now[2] * r12.z - g_now[1] * r13.z);
forceM12.x = (0.25 / A_T) * (g_now[0] * r13.x - g_now[1] * r12.x);
forceM12.y = (0.25 / A_T) * (g_now[0] * r13.y - g_now[1] * r12.y);
forceM12.z = (0.25 / A_T) * (g_now[0] * r13.z - g_now[1] * r12.z);
if (vertex_index == vf[0])
{
//v1
Fx += -(forceM11.x + forceM12.x);
Fy += -(forceM11.y + forceM12.y);
Fz += -(forceM11.z + forceM12.z);
}
else if (vertex_index == vf[1])
{
//v2
Fx += forceM11.x;
Fy += forceM11.y;
Fz += forceM11.z;
}
else if (vertex_index == vf[2])
{
//v2
Fx += forceM12.x;
Fy += forceM12.y;
Fz += forceM12.z;
}
}
he_pair_next = _system.halfedges[he_pair].next;
he = he_pair_next;
} while ((he != first));
grad[vertex_index].x = Fx;
grad[vertex_index].y = Fy;
grad[vertex_index].z = Fz;
sum+= Fx * ref_grad[vertex_index].x + Fy * ref_grad[vertex_index].y + Fz * ref_grad[vertex_index].z;
}
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 ConstraintArea::compute_ref_gradient(void)
{
this->compute_gradient();
ref_grad = grad;
}
void ConstraintArea::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;
pymemb::enforce_periodic(_system.vertices[vertex_index].r, _system.vertices[vertex_index].ip, _system.get_box());
}
}