Program Listing for File potentialSubstrateCylinder.cpp#

Return to documentation for file (pymembrane/cppmodule/src/potentials/potentialSubstrateCylinder.cpp)

#include "potentialSubstrateCylinder.hpp"

bool isOutsideCylinder(real3 vertex_position,
    real3 axis,
    real3 cylinder_position,
    real radius)
{
    real3 cv = pymemb::vector_subtract(vertex_position, cylinder_position);
    real x = pymemb::vector_dot(cv, axis);
    real3 proj;
    Xvec1(proj, x, axis);
    proj = pymemb::vector_sum(cylinder_position, proj);
    real value = pymemb::vector_squared_length(cv) - pymemb::vector_squared_length(proj) - radius*radius;
    return value >= 0;
}

void ProjectOnCylinderSurface(HE_VertexProp *vertices, int vertex_index, real radius, real3 proj)
{
    real3 fpush = pymemb::vector_subtract(vertices[vertex_index].r, proj);
    fpush = pymemb::unit_vector(fpush);
    Xvec1(fpush, radius, fpush);
    vertices[vertex_index].r = pymemb::vector_sum(proj, fpush);
    vertices[vertex_index].type = 2;
}

void ComputeVertexLimitForce_fn(int Numvertices,
                                HE_VertexProp *vertices,
                                real3 axis,
                                real3 cylinder_position,
                                real radius,
                                int* outside_cyl_count)
{
    for (int vertex_index=0; vertex_index < Numvertices; vertex_index++)
    {
        real3 vertex_position = vertices[vertex_index].r;

        real3 cv = pymemb::vector_subtract(vertex_position, cylinder_position);
        real x = pymemb::vector_dot(cv, axis);
        real3 proj;
        Xvec1(proj, x, axis);
        proj = pymemb::vector_sum(cylinder_position, proj);
        real value = pymemb::vector_length(pymemb::vector_subtract(proj, vertex_position)) - (radius);

        if (value < 0 )
        {
            ProjectOnCylinderSurface(vertices, vertex_index, radius, proj);
        }
        else
        {
            outside_cyl_count[vertex_index]++;
        }
    }
}

void ComputeVertexSubstrateCylinderEnergy::compute(void)
{
    real3 axis, position;
    std::vector<int> outside_cyl_count = std::vector<int>(_system.Numvertices, 0);
    for (int i=0; i<m_nbcyl[0]; i++)
    {
        axis.x = m_axis[i*3];
        axis.y = m_axis[i*3+1];
        axis.z = m_axis[i*3+2];
        position.x = m_position[i*3];
        position.y = m_position[i*3+1];
        position.z = m_position[i*3+2];

        ComputeVertexLimitForce_fn(_system.Numvertices,
                                    &_system.vertices[0],
                                    axis,
                                    position,
                                    m_radius[i],
                                    &outside_cyl_count[0]);
    }

    for (int vertex_index=0; vertex_index<_system.Numvertices; vertex_index++)
    {
        if (outside_cyl_count[vertex_index] == m_nbcyl[0])
        {
            if (_system.vertices[vertex_index].type == 2)
            {

                real dist_min = 10000;
                int closest_cyl = 0;
                real3 closest_proj;
                for (int i=0; i<m_nbcyl[0]; i++)
                {
                    axis.x = m_axis[i*3];
                    axis.y = m_axis[i*3+1];
                    axis.z = m_axis[i*3+2];
                    position.x = m_position[i*3];
                    position.y = m_position[i*3+1];
                    position.z = m_position[i*3+2];
                    real3 vertex_position = _system.vertices[vertex_index].r;

                    real3 cv = pymemb::vector_subtract(vertex_position, position);
                    real x = pymemb::vector_dot(cv, axis);
                    real3 proj;
                    Xvec1(proj, x, axis);
                    proj = pymemb::vector_sum(position, proj);
                    real dist = pymemb::vector_length(pymemb::vector_subtract(proj, vertex_position));
                    if (dist < dist_min)
                    {
                        dist_min = dist;
                        closest_cyl = i;
                        closest_proj = proj;
                    }
                }
                ProjectOnCylinderSurface(&_system.vertices[0], vertex_index, m_radius[closest_cyl], closest_proj);
            }
            else
                _system.vertices[vertex_index].type = 1;
        }
        else
            _system.vertices[vertex_index].type = 2;
    }
}