Program Listing for File potentialHarmonicSloutskin.cpp#

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

#include "potentialHarmonicSloutskin.hpp"

inline real ComputeEdgeHarmonicSpinEnergy(const real3 &rij,
                                          const real &k,
                                          const real &l0)
{
    auto dr = sqrt(vdot(rij, rij));
    return (0.5 * k * (dr - l0) * (dr - l0));
}

inline real ComputeEdgeHarmonicSpinEnergy_ferro(const real &s1,
                                                const real &s2,
                                                const real &J)
{
    return (-J * s1 * s2);
}

void ComputeVertexHarmonicSpinEnergy_fn(const int Numedges,
                                        HE_EdgeProp *edges,
                                        const HE_VertexProp *__restrict__ vertices,
                                        const real *__restrict__ _k,
                                        const real *__restrict__ _l0,
                                        const real *__restrict__ _J,
                                        const BoxType &_box)
{
    for (int edge_index = 0; edge_index < Numedges; edge_index++)
    {

        int type = edges[edge_index].type;
        int v1 = edges[edge_index].i;
        auto r1 = vertices[v1].r;
        int v2 = edges[edge_index].j;
        auto r2 = vertices[v2].r;
        auto rij = pymemb::vector_subtract(r2, r1, _box);

        auto s1 = vertices[v1].spin;
        auto s2 = vertices[v2].spin;

        // Harmonic Energy
        double energy = ComputeEdgeHarmonicSpinEnergy(rij, _k[type], _l0[type]);
        // Ferromagnetic Energy
        energy += ComputeEdgeHarmonicSpinEnergy_ferro(s1, s2, _J[type]);

        edges[edge_index].energy += energy;
    }
}

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;
    auto r1 = _system.vertices[v1].r;
    int v2 = _system.edges[query_edge_index].j;
    auto r2 = _system.vertices[v2].r;
    auto rij = pymemb::vector_subtract(r2, r1, _system.get_box());

    auto s1 = _system.vertices[v1].spin;
    auto s2 = _system.vertices[v2].spin;

    // Harmonic Energy
    double edge_energy = ComputeEdgeHarmonicSpinEnergy(rij, 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;
    do
    {

        auto edge_index = _system.halfedges[he].edge;
        auto type = _system.edges[edge_index].type;
        auto v1 = _system.edges[edge_index].i;
        auto v2 = _system.edges[edge_index].j;

        auto r1 = _system.vertices[v1].r;
        auto r2 = _system.vertices[v2].r;
        auto rij = pymemb::vector_subtract(r2, r1, _system.get_box());
        harmonic_energy += 0.5 * ComputeEdgeHarmonicSpinEnergy(rij, k[type], l0[type]);

        auto s1 = _system.vertices[v1].spin;
        auto s2 = _system.vertices[v2].spin;
        ferro_energy += 0.5 * ComputeEdgeHarmonicSpinEnergy_ferro(s1, s2, J[type]);

        int he_pair = _system.halfedges[he].pair;
        he = _system.halfedges[he_pair].next;
    } while ((he != first));

    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 + ferro_energy;
    return energy;
}

void ComputeVertexHarmonicSpinEnergy::compute_energy(void)
{

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

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_fn(const int Numedges,
                                       HE_VertexProp *vertices,
                                       const HE_EdgeProp *__restrict__ edges,
                                       const double *__restrict__ _k,
                                       const double *__restrict__ _l0,
                                       const BoxType &_box)
{
    for (int edge_index = 0; edge_index < Numedges; edge_index++)
    {

        int type = edges[edge_index].type;
        int v1 = edges[edge_index].i;
        auto r1 = vertices[v1].r;
        int v2 = edges[edge_index].j;
        auto r2 = vertices[v2].r;
        auto rij = pymemb::vector_subtract(r2, r1, _box);

        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_fn(_system.Numedges,
                                      &_system.vertices[0],
                                      &_system.edges[0],
                                      &k[0],
                                      &l0[0],
                                      _system.get_box());
}