Program Listing for File potentialBending.cpp#
↰ Return to documentation for file (pymembrane/cppmodule/src/potentials/potentialBending.cpp
)
#include "potentialBending.hpp"
real ComputeVertexBendingEnergy_lambda(const real3 &nk,
const real3 &nl,
const real3 &nk_ref,
const real3 &nl_ref,
const real &kappa_tilde)
{
real norm_nk = sqrt(vdot(nk, nk));
real norm_nl = sqrt(vdot(nl, nl));
real nknl = vdot(nk, nl) / (norm_nk * norm_nl);
real norm_nk_ref = sqrt(vdot(nk_ref, nk_ref));
real norm_nl_ref = sqrt(vdot(nl_ref, nl_ref));
real nknl_ref = vdot(nk_ref, nl_ref) / (norm_nk_ref * norm_nl_ref);
real energy = kappa_tilde * (1.0 - nknl * nknl_ref - sqrt(fabs(1.0 - nknl * nknl)) * sqrt((1.0 - nknl_ref * nknl_ref)));
// real energy = kappa_tilde*(1.0 - nknl);
return energy;
}
void ComputeVertexBendingEnergy_fn(int Numedges,
HE_EdgeProp *edges,
const HE_FaceProp *faces,
const HE_VertexProp *vertices,
const real *_kappa,
const BoxType _box)
{
for (int edge_index = 0; edge_index < Numedges; edge_index++)
{
if (edges[edge_index].boundary == false)
{
int type = edges[edge_index].type;
real kappa_tilde = (2.0 / sqrt(3.0)) * (_kappa[type]); // kappa
int v0 = edges[edge_index].v0;
int v1 = edges[edge_index].v1;
int v2 = edges[edge_index].v2;
int v3 = edges[edge_index].v3;
real3 r0 = vertices[v0].r;
real3 r1 = vertices[v1].r;
real3 r2 = vertices[v2].r;
real3 r3 = vertices[v3].r;
real3 nk, nl;
nk = pymemb::compute_normal_triangle(r0, r1, r2, _box);
nl = pymemb::compute_normal_triangle(r0, r2, r3, _box);
real3 nk_ref, nl_ref;
nk_ref = faces[edges[edge_index].face_k].normal_reference;
nl_ref = faces[edges[edge_index].face_l].normal_reference;
real energy = ComputeVertexBendingEnergy_lambda(nk, nl, nk_ref, nl_ref, kappa_tilde);
edges[edge_index].energy += energy;
}
}
}
void ComputeVertexBendingEnergy::compute_energy(void)
{
ComputeVertexBendingEnergy_fn(_system.Numedges,
&_system.edges[0],
&_system.faces[0],
&_system.vertices[0],
&m_kappa[0],
_system.get_box());
}
real ComputeVertexBendingEnergy::compute_edge_energy(int query_edge_index)
{
// we need to loop the 4 edges that are connected to the edge_index
auto edge_index_vec = _system.get_edge_neighbours_host(query_edge_index);
// reset energy
real edge_energy = 0.0;
for (auto edge_index : edge_index_vec)
{
if (_system.edges[edge_index].boundary == false)
{
int type = _system.edges[edge_index].type;
real kappa_tilde = (2.0 / sqrt(3.0)) * (m_kappa[type]); // kappa
int v0 = _system.edges[edge_index].v0;
int v1 = _system.edges[edge_index].v1;
int v2 = _system.edges[edge_index].v2;
int v3 = _system.edges[edge_index].v3;
real3 r0 = _system.vertices[v0].r;
real3 r1 = _system.vertices[v1].r;
real3 r2 = _system.vertices[v2].r;
real3 r3 = _system.vertices[v3].r;
real3 nk, nl;
nk = pymemb::compute_normal_triangle(r0, r1, r2, _system.get_box());
nl = pymemb::compute_normal_triangle(r0, r2, r3, _system.get_box());
real3 nk_ref, nl_ref;
nk_ref = _system.faces[_system.edges[edge_index].face_k].normal_reference;
nl_ref = _system.faces[_system.edges[edge_index].face_l].normal_reference;
edge_energy += ComputeVertexBendingEnergy_lambda(nk, nl, nk_ref, nl_ref, kappa_tilde);
}
}
return edge_energy;
}
real ComputeVertexBendingEnergy::compute_vertex_energy(int query_vertex_index)
{
real energy = 0.0;
int he = _system.vertices[query_vertex_index]._hedge;
int first = he;
int he_vec[2];
do
{
he_vec[0] = he;
he_vec[1] = _system.halfedges[he].next;
for (auto he_index : he_vec)
{
int edge_index = _system.halfedges[he_index].edge;
if (_system.edges[edge_index].boundary == false)
{
int type = _system.edges[edge_index].type;
real kappa_tilde = (2.0 / sqrt(3.0)) * (m_kappa[type]); // kappa
int v0 = _system.edges[edge_index].v0;
int v1 = _system.edges[edge_index].v1;
int v2 = _system.edges[edge_index].v2;
int v3 = _system.edges[edge_index].v3;
real3 r0 = _system.vertices[v0].r;
real3 r1 = _system.vertices[v1].r;
real3 r2 = _system.vertices[v2].r;
real3 r3 = _system.vertices[v3].r;
real3 nk, nl;
nk = pymemb::compute_normal_triangle(r0, r1, r2, _system.get_box());
nl = pymemb::compute_normal_triangle(r0, r2, r3, _system.get_box());
real3 nk_ref, nl_ref;
nk_ref = _system.faces[_system.edges[edge_index].face_k].normal_reference;
nl_ref = _system.faces[_system.edges[edge_index].face_l].normal_reference;
energy += ComputeVertexBendingEnergy_lambda(nk, nl, nk_ref, nl_ref, kappa_tilde);
}
}
int he_prev = _system.halfedges[he].prev;
he = _system.halfedges[he_prev].pair;
} while (he != first);
return energy;
}
forceMatrix ComputeVertexBendingForce_lambda(const real3 &r0,
const real3 &r1,
const real3 &r2,
const real3 &r3,
const real &kappa_tilde,
const BoxType &_box)
{
real3 r01, r02, r03;
real3 nk, nl;
real3 forceM11, forceM12, forceM13;
nk = pymemb::compute_normal_triangle(r0, r1, r2, _box);
real Ak = 0.5 * sqrt(vdot(nk, nk));
nl = pymemb::compute_normal_triangle(r0, r2, r3, _box);
real Al = 0.5 * sqrt(vdot(nl, nl));
real s = vdot(nk, nl);
// printf("Ak,Al (%f,%f)\n", Ak, Al);
r01 = pymemb::vector_subtract(r1, r0, _box);
r02 = pymemb::vector_subtract(r2, r0, _box);
r03 = pymemb::vector_subtract(r3, r0, _box);
real r01_dot_r02 = vdot(r01, r02);
real r01_dot_r03 = vdot(r01, r03);
real r02_dot_r03 = vdot(r02, r03);
real r01_dot_r01 = vdot(r01, r01);
real r02_dot_r02 = vdot(r02, r02);
real r03_dot_r03 = vdot(r03, r03);
forceM11.x = forceM11.y = forceM11.z = 0.0;
forceM12.x = forceM12.y = forceM12.z = 0.0;
forceM13.x = forceM13.y = forceM13.z = 0.0;
//(r02 · r03) r02 − (r02 · r02) r03
//(r02 · r03) r01 + (r01 · r02) r03 − 2 (r01 · r03) r02
//(r01 · r02) r02 − (r02 · r02) r01
forceM11.x += (r02_dot_r03)*r02.x - (r02_dot_r02)*r03.x;
forceM11.y += (r02_dot_r03)*r02.y - (r02_dot_r02)*r03.y;
forceM11.z += (r02_dot_r03)*r02.z - (r02_dot_r02)*r03.z;
forceM12.x += (r02_dot_r03)*r01.x + (r01_dot_r02)*r03.x - 2.0 * (r01_dot_r03)*r02.x;
forceM12.y += (r02_dot_r03)*r01.y + (r01_dot_r02)*r03.y - 2.0 * (r01_dot_r03)*r02.y;
forceM12.z += (r02_dot_r03)*r01.z + (r01_dot_r02)*r03.z - 2.0 * (r01_dot_r03)*r02.z;
forceM13.x += (r01_dot_r02)*r02.x - (r02_dot_r02)*r01.x;
forceM13.y += (r01_dot_r02)*r02.y - (r02_dot_r02)*r01.y;
forceM13.z += (r01_dot_r02)*r02.z - (r02_dot_r02)*r01.z;
//(-s/(4*Ak*Ak))((r02 · r02) r01 − (r01 · r02) r02)
//(-s/(4*Ak*Ak))(r01 · r01) r02 − (r01 · r02) r01
// 0
forceM11.x += (-s / (4.0 * Ak * Ak)) * ((r02_dot_r02)*r01.x - (r01_dot_r02)*r02.x);
forceM11.y += (-s / (4.0 * Ak * Ak)) * ((r02_dot_r02)*r01.y - (r01_dot_r02)*r02.y);
forceM11.z += (-s / (4 * Ak * Ak)) * ((r02_dot_r02)*r01.z - (r01_dot_r02)*r02.z);
forceM12.x += (-s / (4.0 * Ak * Ak)) * ((r01_dot_r01)*r02.x - (r01_dot_r02)*r01.x);
forceM12.y += (-s / (4.0 * Ak * Ak)) * ((r01_dot_r01)*r02.y - (r01_dot_r02)*r01.y);
forceM12.z += (-s / (4.0 * Ak * Ak)) * ((r01_dot_r01)*r02.z - (r01_dot_r02)*r01.z);
// 0
//(-s/(4*Al*Al))((r03 · r03) r02 − (r02 · r03) r03)
//(-s/(4*Al*Al))((r02 · r02) r03 − (r02 · r03) r02)
forceM12.x += (-s / (4.0 * Al * Al)) * ((r03_dot_r03)*r02.x - (r02_dot_r03)*r03.x);
forceM12.y += (-s / (4.0 * Al * Al)) * ((r03_dot_r03)*r02.y - (r02_dot_r03)*r03.y);
forceM12.z += (-s / (4.0 * Al * Al)) * ((r03_dot_r03)*r02.z - (r02_dot_r03)*r03.z);
forceM13.x += (-s / (4.0 * Al * Al)) * ((r02_dot_r02)*r03.x - (r02_dot_r03)*r02.x);
forceM13.y += (-s / (4.0 * Al * Al)) * ((r02_dot_r02)*r03.y - (r02_dot_r03)*r02.y);
forceM13.z += (-s / (4.0 * Al * Al)) * ((r02_dot_r02)*r03.z - (r02_dot_r03)*r02.z);
real factor = kappa_tilde / (4.0 * Ak * Al);
forceM11.x *= factor;
forceM12.x *= factor;
forceM13.x *= factor;
forceM11.y *= factor;
forceM12.y *= factor;
forceM13.y *= factor;
forceM11.z *= factor;
forceM12.z *= factor;
forceM13.z *= factor;
forceMatrix result;
result.forceM11 = forceM11;
result.forceM12 = forceM12;
result.forceM13 = forceM13;
return result;
}
forceMatrix scale_BendingForceMatrix_lambda(const real3 nk,
const real3 nl,
const real3 nk_ref,
const real3 nl_ref,
forceMatrix fval)
{
real norm_nk = sqrt(vdot(nk, nk));
real norm_nl = sqrt(vdot(nl, nl));
real nknl = vdot(nk, nl) / (norm_nk * norm_nl);
real fac_nknl = 1.0 - nknl * nknl;
real norm_nk_ref = sqrt(vdot(nk_ref, nk_ref));
real norm_nl_ref = sqrt(vdot(nl_ref, nl_ref));
real nknl_ref = vdot(nk_ref, nl_ref) / (norm_nk_ref * norm_nl_ref);
real fac_nknl_ref = 1.0 - nknl_ref * nknl_ref;
real factor = 0.0;
if (fac_nknl > 0.0 && fac_nknl_ref >= 0.0) // save guard for ridges and weird cases
{
factor = nknl_ref * (1.0 - sqrt(fac_nknl_ref / fac_nknl));
}
/*else
{
printf("err fac_nknl = %f fac_nknl_ref = %f \n",fac_nknl, fac_nknl_ref);
}*/
fval.forceM11.x *= factor;
fval.forceM12.x *= factor;
fval.forceM13.x *= factor;
fval.forceM11.y *= factor;
fval.forceM12.y *= factor;
fval.forceM13.y *= factor;
fval.forceM11.z *= factor;
fval.forceM12.z *= factor;
fval.forceM13.z *= factor;
return fval;
}
void ComputeVertexBendingForce_fn(int Numedges,
const HE_EdgeProp *edges,
const HE_FaceProp *faces,
HE_VertexProp *vertices,
const real *_kappa,
const BoxType _box)
{
for (int edge_index = 0; edge_index < Numedges; edge_index++)
{
if (edges[edge_index].boundary == false)
{
int type = edges[edge_index].type;
real kappa_tilde = (2.0 / sqrt(3.0)) * (_kappa[type]); // kappa
int v0 = edges[edge_index].v0;
int v1 = edges[edge_index].v1;
int v2 = edges[edge_index].v2;
int v3 = edges[edge_index].v3;
real3 r0 = vertices[v0].r;
real3 r1 = vertices[v1].r;
real3 r2 = vertices[v2].r;
real3 r3 = vertices[v3].r;
forceMatrix gradEe = ComputeVertexBendingForce_lambda(r0, r1, r2, r3, kappa_tilde, _box);
/* Scale matrix of force by reference configuration*/
real3 nk, nl;
nk = pymemb::compute_normal_triangle(r0, r1, r2);
nl = pymemb::compute_normal_triangle(r0, r2, r3);
real3 nk_ref, nl_ref;
nk_ref = faces[edges[edge_index].face_k].normal_reference;
nl_ref = faces[edges[edge_index].face_l].normal_reference;
// std::cout<<"nk_ref:"<<nk_ref.x<<","<<nk_ref.y<<","<<nk_ref.z<<"\n"<<" nl_ref:"<<nl_ref.x<<","<<nl_ref.y<<","<<nl_ref.z<<std::endl;
// forceMatrix fval = gradEe;//scale_BendingForceMatrix_lambda(nk ,nl, nk_ref, nl_ref, gradEe);
forceMatrix fval = scale_BendingForceMatrix_lambda(nk, nl, nk_ref, nl_ref, gradEe);
// v0
vertices[v0].forceC.x += -fval.forceM11.x - fval.forceM12.x - fval.forceM13.x;
vertices[v0].forceC.y += -fval.forceM11.y - fval.forceM12.y - fval.forceM13.y;
vertices[v0].forceC.z += -fval.forceM11.z - fval.forceM12.z - fval.forceM13.z;
// v1
vertices[v1].forceC.x += fval.forceM11.x;
vertices[v1].forceC.y += fval.forceM11.y;
vertices[v1].forceC.z += fval.forceM11.z;
// v2
vertices[v2].forceC.x += fval.forceM12.x;
vertices[v2].forceC.y += fval.forceM12.y;
vertices[v2].forceC.z += fval.forceM12.z;
// v3
vertices[v3].forceC.x += fval.forceM13.x;
vertices[v3].forceC.y += fval.forceM13.y;
vertices[v3].forceC.z += fval.forceM13.z;
}
}
}
void ComputeVertexBendingEnergy::compute(void)
{
ComputeVertexBendingForce_fn(_system.Numedges,
&_system.edges[0],
&_system.faces[0],
&_system.vertices[0],
&m_kappa[0],
_system.get_box());
}
void ComputeVertexBendingStress_fn(const int Numedges,
HE_EdgeProp *edges,
const HE_FaceProp *__restrict__ faces,
const HE_VertexProp *__restrict__ vertices,
const real *__restrict__ _kappa,
realTensor *stress_group_edges,
const BoxType _box)
{
for (int edge_index = 0; edge_index < Numedges; edge_index++)
{
if (edges[edge_index].boundary == false)
{
int type = edges[edge_index].type;
// real kappa_tilde = (2.0 / sqrt(3.0)) * (_kappa[type]); //kappa
real kappa_tilde = _kappa[type];
int v0 = edges[edge_index].v0;
int v1 = edges[edge_index].v1;
int v2 = edges[edge_index].v2;
int v3 = edges[edge_index].v3;
real3 r0 = vertices[v0].r;
real3 r1 = vertices[v1].r;
real3 r2 = vertices[v2].r;
real3 r3 = vertices[v3].r;
forceMatrix gradEe = ComputeVertexBendingForce_lambda(r0, r1, r2, r3, kappa_tilde, _box);
/* Scale matrix of force by reference configuration*/
real3 nk, nl;
nk = pymemb::compute_normal_triangle(r0, r1, r2, _box);
nl = pymemb::compute_normal_triangle(r0, r2, r3, _box);
real3 nk_ref, nl_ref;
nk_ref = faces[edges[edge_index].face_k].normal_reference;
nl_ref = faces[edges[edge_index].face_l].normal_reference;
// forceMatrix fval = gradEe;//scale_BendingForceMatrix_lambda(nk ,nl, nk_ref, nl_ref, gradEe);
forceMatrix fval = scale_BendingForceMatrix_lambda(nk, nl, nk_ref, nl_ref, gradEe);
// if (edge_index < 10)
// printf("type = %i kappa_tilde = %f fval = (%f,%f,%f,%f,%f,%f,%f,%f,%f)\n", type, kappa_tilde, fval.forceM11.x, fval.forceM12.x, fval.forceM13.x, fval.forceM11.y, fval.forceM12.y, fval.forceM13.y, fval.forceM11.z, fval.forceM12.z, fval.forceM13.z);
// This might be wrong so have to be checked
// double check J. Chem. Phys. 131, 154107 (2009) page 4 Eq. 21
// Assume that v0 is in the local replica then construct the r1, r2, r3 based on it
real3 r01, r02, r03;
r01 = pymemb::vector_subtract(r1, r0, _box);
r02 = pymemb::vector_subtract(r2, r0, _box);
r03 = pymemb::vector_subtract(r3, r0, _box);
real3 uw_r3, uw_r2, uw_r1 /*,uw_r0,*/;
// uw_r0 = r0;
uw_r1 = pymemb::vector_sum(r0, r01);
uw_r2 = pymemb::vector_sum(r0, r02);
uw_r3 = pymemb::vector_sum(r0, r03);
real3 F3, F2, F1, F0;
F0.x = -fval.forceM11.x - fval.forceM12.x - fval.forceM13.x;
F0.y = -fval.forceM11.y - fval.forceM12.y - fval.forceM13.y;
F0.z = -fval.forceM11.z - fval.forceM12.z - fval.forceM13.z;
F1.x = fval.forceM11.x;
F1.y = fval.forceM11.y;
F1.z = fval.forceM11.z;
F2.x = fval.forceM12.x;
F2.y = fval.forceM12.y;
F2.z = fval.forceM12.z;
F3.x = fval.forceM13.x;
F3.y = fval.forceM13.y;
F3.z = fval.forceM13.z;
stress_group_edges[edge_index].xx += r0.x * F0.x + uw_r1.x * F1.x + uw_r2.x * F2.x + uw_r3.x * F3.x;
stress_group_edges[edge_index].xy += r0.x * F0.y + uw_r1.x * F1.y + uw_r2.x * F2.y + uw_r3.x * F3.y;
stress_group_edges[edge_index].xz += r0.x * F0.z + uw_r1.x * F1.z + uw_r2.x * F2.z + uw_r3.x * F3.z;
stress_group_edges[edge_index].yx += r0.y * F0.x + uw_r1.y * F1.x + uw_r2.y * F2.x + uw_r3.y * F3.x;
stress_group_edges[edge_index].yy += r0.y * F0.y + uw_r1.y * F1.y + uw_r2.y * F2.y + uw_r3.y * F3.y;
stress_group_edges[edge_index].yz += r0.y * F0.z + uw_r1.y * F1.z + uw_r2.y * F2.z + uw_r3.y * F3.z;
stress_group_edges[edge_index].zx += r0.z * F0.x + uw_r1.z * F1.x + uw_r2.z * F2.x + uw_r3.z * F3.x;
stress_group_edges[edge_index].zy += r0.z * F0.y + uw_r1.z * F1.y + uw_r2.z * F2.y + uw_r3.z * F3.y;
stress_group_edges[edge_index].zz += r0.z * F0.z + uw_r1.z * F1.z + uw_r2.z * F2.z + uw_r3.z * F3.z;
}
}
}
void ComputeVertexBendingEnergy::compute_stress(void)
{
ComputeVertexBendingStress_fn(_system.Numedges,
&_system.edges[0],
&_system.faces[0],
&_system.vertices[0],
&m_kappa[0],
&_system.stress_group_edges[0],
_system.get_box());
}
void ComputeVertexBendingStressAtom_fn(const int Numedges,
HE_EdgeProp *edges,
const HE_FaceProp *__restrict__ faces,
const HE_VertexProp *__restrict__ vertices,
const real *__restrict__ _kappa,
realTensor *stress_virial_atom,
const BoxType _box)
{
for (int edge_index = 0; edge_index < Numedges; edge_index++)
{
if (edges[edge_index].boundary == false)
{
int type = edges[edge_index].type;
real kappa_tilde = (2.0 / sqrt(3.0)) * (_kappa[type]); // kappa
// real kappa_tilde = _kappa[type];
int v0 = edges[edge_index].v0;
int v1 = edges[edge_index].v1;
int v2 = edges[edge_index].v2;
int v3 = edges[edge_index].v3;
real3 r0 = vertices[v0].r;
real3 r1 = vertices[v1].r;
real3 r2 = vertices[v2].r;
real3 r3 = vertices[v3].r;
forceMatrix gradEe = ComputeVertexBendingForce_lambda(r0, r1, r2, r3, kappa_tilde, _box);
/* Scale matrix of force by reference configuration*/
real3 nk, nl;
nk = pymemb::compute_normal_triangle(r0, r1, r2, _box);
nl = pymemb::compute_normal_triangle(r0, r2, r3, _box);
real3 nk_ref, nl_ref;
nk_ref = faces[edges[edge_index].face_k].normal_reference;
nl_ref = faces[edges[edge_index].face_l].normal_reference;
// forceMatrix fval = gradEe;//scale_BendingForceMatrix_lambda(nk ,nl, nk_ref, nl_ref, gradEe);
forceMatrix fval = scale_BendingForceMatrix_lambda(nk, nl, nk_ref, nl_ref, gradEe);
// if (edge_index < 10)
// printf("type = %i kappa_tilde = %f fval = (%f,%f,%f,%f,%f,%f,%f,%f,%f)\n", type, kappa_tilde, fval.forceM11.x, fval.forceM12.x, fval.forceM13.x, fval.forceM11.y, fval.forceM12.y, fval.forceM13.y, fval.forceM11.z, fval.forceM12.z, fval.forceM13.z);
// This might be wrong so have to be checked
// double check J. Chem. Phys. 131, 154107 (2009) page 4 Eq. 21
// Assume that v0 is in the local replica then construct the r1, r2, r3 based on it
real3 r01, r02, r03;
r01 = pymemb::vector_subtract(r1, r0, _box);
r02 = pymemb::vector_subtract(r2, r0, _box);
r03 = pymemb::vector_subtract(r3, r0, _box);
real3 uw_r3, uw_r2, uw_r1 /*,uw_r0,*/;
// uw_r0 = r0;
uw_r1 = pymemb::vector_sum(r0, r01);
uw_r2 = pymemb::vector_sum(r0, r02);
uw_r3 = pymemb::vector_sum(r0, r03);
real3 F3, F2, F1, F0;
F0.x = -fval.forceM11.x - fval.forceM12.x - fval.forceM13.x;
F0.y = -fval.forceM11.y - fval.forceM12.y - fval.forceM13.y;
F0.z = -fval.forceM11.z - fval.forceM12.z - fval.forceM13.z;
F1.x = fval.forceM11.x;
F1.y = fval.forceM11.y;
F1.z = fval.forceM11.z;
F2.x = fval.forceM12.x;
F2.y = fval.forceM12.y;
F2.z = fval.forceM12.z;
F3.x = fval.forceM13.x;
F3.y = fval.forceM13.y;
F3.z = fval.forceM13.z;
realTensor stress_group_edge;
stress_group_edge.xx = r0.x * F0.x + uw_r1.x * F1.x + uw_r2.x * F2.x + uw_r3.x * F3.x;
stress_group_edge.xy = r0.x * F0.y + uw_r1.x * F1.y + uw_r2.x * F2.y + uw_r3.x * F3.y;
stress_group_edge.xz = r0.x * F0.z + uw_r1.x * F1.z + uw_r2.x * F2.z + uw_r3.x * F3.z;
stress_group_edge.yx = r0.y * F0.x + uw_r1.y * F1.x + uw_r2.y * F2.x + uw_r3.y * F3.x;
stress_group_edge.yy = r0.y * F0.y + uw_r1.y * F1.y + uw_r2.y * F2.y + uw_r3.y * F3.y;
stress_group_edge.yz = r0.y * F0.z + uw_r1.y * F1.z + uw_r2.y * F2.z + uw_r3.y * F3.z;
stress_group_edge.zx = r0.z * F0.x + uw_r1.z * F1.x + uw_r2.z * F2.x + uw_r3.z * F3.x;
stress_group_edge.zy = r0.z * F0.y + uw_r1.z * F1.y + uw_r2.z * F2.y + uw_r3.z * F3.y;
stress_group_edge.zz = r0.z * F0.z + uw_r1.z * F1.z + uw_r2.z * F2.z + uw_r3.z * F3.z;
int vvec[4] = {v0, v1, v2, v3};
#pragma unroll
for (auto v : vvec)
{
stress_virial_atom[v].xx += 0.25 * stress_group_edge.xx;
stress_virial_atom[v].xy += 0.25 * stress_group_edge.xy;
stress_virial_atom[v].xz += 0.25 * stress_group_edge.xz;
stress_virial_atom[v].yx += 0.25 * stress_group_edge.yx;
stress_virial_atom[v].yy += 0.25 * stress_group_edge.yy;
stress_virial_atom[v].yz += 0.25 * stress_group_edge.yz;
stress_virial_atom[v].zx += 0.25 * stress_group_edge.zx;
stress_virial_atom[v].zy += 0.25 * stress_group_edge.zy;
stress_virial_atom[v].zz += 0.25 * stress_group_edge.zz;
}
}
}
}
void ComputeVertexBendingEnergy::compute_atomic_stress(void)
{
ComputeVertexBendingStressAtom_fn(_system.Numedges,
&_system.edges[0],
&_system.faces[0],
&_system.vertices[0],
&m_kappa[0],
&_system.stress_virial_atom[0],
_system.get_box());
}