Program Listing for File potentialHarmonicDye.cpp#

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

#include "potentialHarmonicDye.hpp"



double ComputeEdgeHarmonicSpinEnergy(const real3 r1,
                                 const real3 r2,
                                 const double k,
                                 const double l0)
{
    real3 rij;
    vsub(rij, r2, r1);

    double dr = sqrt(vdot(rij, rij));

    double energy = 0.5 * k * (dr - l0) * (dr - l0);

    return energy;
}

double ComputeEdgeHarmonicSpinEnergy_ferro(const real s1,
                                  const real s2,
                                  const double J)
{
    auto H = -J*s1*s2;
    return H;
}

void ComputeVertexHarmonicSpinEnergy_kernel(const int Numedges,
                                        HE_EdgeProp *edges,
                                        const HE_VertexProp *vertices,
                                        const double *__restrict__ _k,
                                        const double *__restrict__ _l0,
                                        const double *__restrict__ _J)
{
    for (int edge_index = 0; edge_index < Numedges; edge_index++)
    {
        int type = edges[edge_index].type;

        int v1 = edges[edge_index].i;
        real3 _r1 = vertices[v1].r;
        auto _s1 = vertices[v1].spin;

        int v2 = edges[edge_index].j;
        real3 _r2 = vertices[v2].r;
        auto _s2 = vertices[v2].spin;

        auto _vtype1 = vertices[v1].type;
        auto _vtype2 = vertices[v2].type;

        //Harmonic Energy
        //Free vertices have the full interaction. Vertices at the edge of a particle-covered
        //surface area exhibit only half the interaction with their NN free vertices.
        //Vertices covered by a particle do not interact between themselves.
        double energy;
        if ((_vtype1==-1) && (_vtype2==-1))
            energy = ComputeEdgeHarmonicSpinEnergy(_r1, _r2, _k[type], _l0[type]);
        if (((_vtype1==-1) && (_vtype2>=0)) || ((_vtype1>=0) && (_vtype2==-1)))
            energy = 0.5*ComputeEdgeHarmonicSpinEnergy(_r1, _r2, _k[type], _l0[type]);


        //COMMENTED FERRO ENERGY (no spins in particle-on-drop systems)
        //Ferromagnetic Energy
        //energy+=ComputeEdgeHarmonicSpinEnergy_ferro(_s1, _s2, _J[type]);

        edges[edge_index].energy += energy;
    }

/*  double ener_tot;
    for (int edge_index = 0; edge_index < Numedges; edge_index++) {
        ener_tot+=edges[edge_index].energy;
    }
    std::cout << "Total: " << ener_tot << std::endl; */

}

double ComputeVertexHarmonicSpinEnergy::compute_edge_energy(int query_edge_index)
{
    int type = _system.edges[query_edge_index].type;
    int v1 = _system.edges[query_edge_index].i;
    real3 _r1 = _system.vertices[v1].r;
    auto _s1 = _system.vertices[v1].spin;

    int v2 = _system.edges[query_edge_index].j;
    real3 _r2 = _system.vertices[v2].r;
    auto _s2 = _system.vertices[v2].spin;

    //Harmonic Energy
    double edge_energy = ComputeEdgeHarmonicSpinEnergy(_r1, _r2, k[type], l0[type]);

    //Ferromagnetic Energy
    edge_energy+=ComputeEdgeHarmonicSpinEnergy_ferro(_s1, _s2, J[type]);
    return edge_energy;
}

double ComputeVertexHarmonicSpinEnergy::compute_vertex_energy(int query_vertex_index)
{

    double harmonic_energy = 0.0;
    //double ferro_energy = 0.0;
    int he = _system.vertices[query_vertex_index]._hedge;
    int first = he;

    if (_system.vertices[query_vertex_index].type==-1) {    //ELI: If we deal here with the energy of a particle-free vertex, do the usual calculation.
        do
        {
            // DO SOMETHING WITH THAT FACE
            int edge_index = _system.halfedges[he].edge;
            int type = _system.edges[edge_index].type;
            int v1 = _system.edges[edge_index].i;
            int v2 = _system.edges[edge_index].j;

            real3 _r1 = _system.vertices[v1].r;
            real3 _r2 = _system.vertices[v2].r;

            //Vertices covered by a particle do not exhibit harmonic energy.
            //Vertices at the edge of a particle-covered area have 1/2 interaction with their
            //free NN vertices.
            auto _vtype1 = _system.vertices[v1].type;
            auto _vtype2 = _system.vertices[v2].type;

            if ((_vtype1==-1) && (_vtype2==-1))
                harmonic_energy += ComputeEdgeHarmonicSpinEnergy(_r1, _r2, k[type], l0[type]); //ELI: Originally, there was a 0.5 factor here. I removed it.
            if (((_vtype1==-1) && (_vtype2>=0)) || ((_vtype1>=0) && (_vtype2==-1)))
                harmonic_energy += 0.5*ComputeEdgeHarmonicSpinEnergy(_r1, _r2, k[type], l0[type]);
            // Note: if ((_vtype1>=0) && (_vtype2>=0)) do nothing, as this is a spring "covered by a colloidal particle".



            //ferro_energy += 0.5*ComputeEdgeHarmonicSpinEnergy_ferro(_s1, _s2, J[type]);

            // MOVE TO THE NEXT FACE
            int he_pair = _system.halfedges[he].pair;
            he = _system.halfedges[he_pair].next;
        } while ((he != first));
    } else if (_system.vertices[query_vertex_index].type==query_vertex_index) {   //ELI: if we deal with a vertex at the center of a particle. Check the energy of this particle's edge.
        int edge_vert_ii;
        edge_vert_ii=_system.vertices[query_vertex_index].mass;
        do
        {
            he = _system.vertices[edge_vert_ii]._hedge;
            first = he;
            do
            {
                // DO SOMETHING WITH THAT FACE
                int edge_index = _system.halfedges[he].edge;
                int type = _system.edges[edge_index].type;
                int v1 = _system.edges[edge_index].i;
                int v2 = _system.edges[edge_index].j;

                real3 _r1 = _system.vertices[v1].r;
                real3 _r2 = _system.vertices[v2].r;

                auto _vtype1 = _system.vertices[v1].type;
                auto _vtype2 = _system.vertices[v2].type;

                if ((_vtype1==-1) && (_vtype2==-1))
                    harmonic_energy += ComputeEdgeHarmonicSpinEnergy(_r1, _r2, k[type], l0[type]);
                if (((_vtype1==-1) && (_vtype2>=0)) || ((_vtype1>=0) && (_vtype2==-1)))
                    harmonic_energy += 0.5*ComputeEdgeHarmonicSpinEnergy(_r1, _r2, k[type], l0[type]);

                // MOVE TO THE NEXT FACE
                int he_pair = _system.halfedges[he].pair;
                he = _system.halfedges[he_pair].next;
            } while ((he != first));
            edge_vert_ii=_system.vertices[edge_vert_ii].mass;
        } while (edge_vert_ii!=-1);

    }


// This block is for
/*     if(_system.vertices[query_vertex_index].spin>0.0)
    {
        auto vertex_type = _system.vertices[query_vertex_index].type;
        harmonic_energy = Ea[vertex_type];
    } */

    auto energy = harmonic_energy; // COMMENTED HERE: + ferro_energy;
    return energy;
}

void ComputeVertexHarmonicSpinEnergy::compute_energy(void)
{

    ComputeVertexHarmonicSpinEnergy_kernel(_system.Numedges,
                                       &_system.edges[0],
                                       &_system.vertices[0],
                                       &k[0],
                                       &l0[0],
                                       &J[0]);
}

double ComputeVertexHarmonicSpinForce(const real3 rij,
                                  const double k,
                                  const double l0)
{
    double dr = sqrt(vdot(rij, rij));
    double fval = k * (dr - l0) / dr;
    return fval;
}

void ComputeVertexHarmonicSpinForce_kernel(const int Numedges,
                                       HE_VertexProp *vertices,
                                       const HE_EdgeProp *__restrict__ edges,
                                       const double *__restrict__ _k,
                                       const double *__restrict__ _l0)
{
    //int i = blockIdx.x*blockDim.x + threadIdx.x;
    //if(  i < Numvertices )
    for (int edge_index = 0; edge_index < Numedges; edge_index++)
    {

        int v1 = edges[edge_index].i;
        real3 _r1 = vertices[v1].r;

        int v2 = edges[edge_index].j;
        real3 _r2 = vertices[v2].r;

        real3 _rij;
        vsub(_rij, _r2, _r1);

        int type = edges[edge_index].type;

        double fval = ComputeVertexHarmonicSpinForce(_rij, _k[type], _l0[type]);

        vertices[v1].forceC.x += fval * _rij.x;
        vertices[v1].forceC.y += fval * _rij.y;
        vertices[v1].forceC.z += fval * _rij.z;

        vertices[v2].forceC.x += -1.0 * fval * _rij.x;
        vertices[v2].forceC.y += -1.0 * fval * _rij.y;
        vertices[v2].forceC.z += -1.0 * fval * _rij.z;
    }
}

void ComputeVertexHarmonicSpinEnergy::compute(void)
{

    ComputeVertexHarmonicSpinForce_kernel(_system.Numedges,
                                      &_system.vertices[0],
                                      &_system.edges[0],
                                      &k[0],
                                      &l0[0]);
}