Program Listing for File wca.hpp#

↰ Return to documentation for file (source/pele/wca.hpp)

#ifndef _PELE_WCA_H
#define _PELE_WCA_H

#include "atomlist_potential.hpp"
#include "base_interaction.hpp"
#include "distance.hpp"
#include "simple_pairwise_ilist.hpp"
#include "simple_pairwise_potential.hpp"

namespace pele {

struct WCA_interaction : BaseInteraction {
  double const _C6, _C12;
  double const _6C6, _12C12, _42C6, _156C12;
  double const _coff2, _eps;  // cutoff distance for WCA potential

  WCA_interaction(double sig, double eps)
      : _C6(sig * sig * sig * sig * sig * sig),
        _C12(_C6 * _C6),
        _6C6(6. * _C6),
        _12C12(12. * _C12),
        _42C6(42 * _C6),
        _156C12(156 * _C12),
        _coff2(pow(2., 1. / 3) * sig * sig),
        _eps(eps) {}

  /* calculate energy from distance squared */
  double energy(double r2, const double dij) const {
    double E;
    double ir2 = 1.0 / r2;
    double ir6 = ir2 * ir2 * ir2;
    double ir12 = ir6 * ir6;
    if (r2 < _coff2)
      E = 4. * _eps * (-_C6 * ir6 + _C12 * ir12) + _eps;
    else
      E = 0.;

    return E;
  }

  /* calculate energy and gradient from distance squared, gradient is in
   * -(dv/drij)/|rij| */
  double energy_gradient(double r2, double *gij, const double dij) const {
    double E;
    double ir2 = 1.0 / r2;
    double ir6 = ir2 * ir2 * ir2;
    double ir12 = ir6 * ir6;
    if (r2 < _coff2) {
      E = 4. * _eps * (-_C6 * ir6 + _C12 * ir12) + _eps;
      *gij = 4. * _eps * (-_6C6 * ir6 + _12C12 * ir12) * ir2;
    } else {
      E = 0.;
      *gij = 0;
    }

    return E;
  }

  double inline energy_gradient_hessian(double r2, double *gij, double *hij,
                                        const double dij) const {
    double E;
    double ir2 = 1.0 / r2;
    double ir6 = ir2 * ir2 * ir2;
    double ir12 = ir6 * ir6;

    if (r2 < _coff2) {
      E = 4. * _eps * (-_C6 * ir6 + _C12 * ir12) + _eps;
      *gij = 4. * _eps * (-_6C6 * ir6 + _12C12 * ir12) * ir2;
      *hij = 4. * _eps * (-_42C6 * ir6 + _156C12 * ir12) * ir2;
    } else {
      E = 0.;
      *gij = 0;
      *hij = 0;
    }

    return E;
  }
};

//
// combine the components (interaction, looping method, distance function) into
// defined classes
//

class WCA
    : public SimplePairwisePotential<WCA_interaction, cartesian_distance<3>> {
 public:
  WCA(double sig, double eps)
      : SimplePairwisePotential<WCA_interaction, cartesian_distance<3>>(
            std::make_shared<WCA_interaction>(sig, eps),
            std::make_shared<cartesian_distance<3>>()) {}
};

class WCA2D
    : public SimplePairwisePotential<WCA_interaction, cartesian_distance<2>> {
 public:
  WCA2D(double sig, double eps)
      : SimplePairwisePotential<WCA_interaction, cartesian_distance<2>>(
            std::make_shared<WCA_interaction>(sig, eps),
            std::make_shared<cartesian_distance<2>>()) {}
};

class WCAPeriodic
    : public SimplePairwisePotential<WCA_interaction, periodic_distance<3>> {
 public:
  WCAPeriodic(double sig, double eps, Array<double> const boxvec)
      : SimplePairwisePotential<WCA_interaction, periodic_distance<3>>(
            std::make_shared<WCA_interaction>(sig, eps),
            std::make_shared<periodic_distance<3>>(boxvec)) {}
};

class WCAPeriodic2D
    : public SimplePairwisePotential<WCA_interaction, periodic_distance<2>> {
 public:
  WCAPeriodic2D(double sig, double eps, Array<double> const boxvec)
      : SimplePairwisePotential<WCA_interaction, periodic_distance<2>>(
            std::make_shared<WCA_interaction>(sig, eps),
            std::make_shared<periodic_distance<2>>(boxvec)) {}
};

class WCANeighborList : public SimplePairwiseNeighborList<WCA_interaction> {
 public:
  WCANeighborList(Array<size_t> &ilist, double sig, double eps)
      : SimplePairwiseNeighborList<WCA_interaction>(
            std::make_shared<WCA_interaction>(sig, eps), ilist) {}
};

class WCAAtomList
    : public AtomListPotential<WCA_interaction, cartesian_distance<3>> {
 public:
  WCAAtomList(double sig, double eps, Array<size_t> atoms1,
              Array<size_t> atoms2)
      : AtomListPotential<WCA_interaction, cartesian_distance<3>>(
            std::make_shared<WCA_interaction>(sig, eps),
            std::make_shared<cartesian_distance<3>>(), atoms1, atoms2) {}
  WCAAtomList(double sig, double eps, Array<size_t> atoms1)
      : AtomListPotential<WCA_interaction, cartesian_distance<3>>(
            std::make_shared<WCA_interaction>(sig, eps),
            std::make_shared<cartesian_distance<3>>(), atoms1) {}
};

}  // namespace pele
#endif