Program Listing for File frenkel.hpp#

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

/******************************+
 * Modified Example from pele to create a frenkel potential
 *
 * The python bindings for this potential are in frenkel.pyx
 *
 */

#ifndef PYGMIN_FRENKEL_H
#define PYGMIN_FRENKEL_H

#include <memory>

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

namespace pele {

struct frenkel_interaction : BaseInteraction {
  double const _eps;
  double const _sig2;
  double const _rcut2;
  double const _prefactor;
  frenkel_interaction(double sig, double eps, double rcut)
      : _eps(eps),
        _sig2(sig * sig),
        _rcut2(rcut * rcut),
        _prefactor(2 * _eps * (_rcut2 / _sig2) *
                   pow(3 / (2 * ((_rcut2 / _sig2) - 1)), 3)) {}

  /* calculate energy from distance squared */
  double inline energy(double r2, double dij) const {
    if (r2 >= _rcut2) {
      return 0.;
    }
    double ir2 = 1.0 / r2;
    double cutoff_factor = _rcut2 * ir2 - 1;
    double sigma_factor = _sig2 * ir2 - 1;
    return _prefactor * cutoff_factor * cutoff_factor * sigma_factor;
  }

  /* calculate energy and gradient from distance squared, gradient is in
   * |g|/|rij| */
  double inline energy_gradient(double r2, double *gij, double dij) const {
    double ir2 = 1.0 / r2;
    double cutoff_factor = _rcut2 * ir2 - 1;
    double sigma_factor = _sig2 * ir2 - 1;
    *gij = -_prefactor *
           (2 * _sig2 * cutoff_factor * cutoff_factor +
            4 * _rcut2 * cutoff_factor * sigma_factor) *
           ir2 * ir2;
    double energy = _prefactor * cutoff_factor * cutoff_factor * sigma_factor;
    return energy;
  }

  double inline energy_gradient_hessian(double r2, double *gij, double *hij,
                                        double dij) const {
    double ir2 = 1.0 / r2;
    double cutoff_factor = _rcut2 * ir2 - 1;
    double sigma_factor = _sig2 * ir2 - 1;
    *gij = -_prefactor *
           (2 * _sig2 * cutoff_factor * cutoff_factor +
            4 * _rcut2 * cutoff_factor * sigma_factor) *
           ir2 * ir2;
    *hij = _prefactor * (16 * _rcut2 * cutoff_factor * _sig2 * ir2 +
                         6 * cutoff_factor * cutoff_factor * _sig2 +
                         8 * _rcut2 * _rcut2 * sigma_factor * ir2 +
                         12 * _rcut2 * cutoff_factor * sigma_factor);
    double energy = _prefactor * cutoff_factor * cutoff_factor * sigma_factor;
    return energy;
  }
};

class Frenkel : public pele::SimplePairwisePotential<frenkel_interaction> {
 public:
  Frenkel(double sig, double eps, double rcut)
      : SimplePairwisePotential<frenkel_interaction>(
            std::make_shared<frenkel_interaction>(sig, eps, rcut)) {}
};

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


template <size_t ndim>
class FrenkelPeriodicCellLists
    : public CellListPotential<frenkel_interaction, periodic_distance<ndim>> {
 public:
  FrenkelPeriodicCellLists(double sig, double eps, double rcut,
                           Array<double> const boxvec, double ncellx_scale)
      : CellListPotential<frenkel_interaction, periodic_distance<ndim>>(
            std::make_shared<frenkel_interaction>(sig, eps, rcut),
            std::make_shared<periodic_distance<ndim>>(boxvec), boxvec, rcut,
            ncellx_scale) {}
};

}  // namespace pele

#endif

//
//

// class Frenkel : public pele::SimplePairwisePotential<frenkel_interaction,
// cartesian_distance<3> > { public:
//   Frenkel(double sig, double eps, double rcut)
//     : SimplePairwisePotential<frenkel_interaction, cartesian_distance<3> >
//     (std::make_shared<frenkel_interaction>(sig, eps, rcut)) {}
// };