Program Listing for File atlj.cpp#

↰ Return to documentation for file (source/atlj.cpp)

#include "pele/atlj.hpp"
#include <array>
#include <iostream>
#include <limits>
#include <math.h>
#include <memory>

// Warning the following files were written to generate basins for ATLJ from
// LBFGS using an exact gradient for a three body potential in 3 dimensions.
// This needs to be expanded on for more than three atoms / different dimensions
// whenever it gets used for more
// A rewrite would be in order for potentials elsewhere;
// The AT gradient is only calculated exactly, the energy isn't
// so you might need to rewrite

// Make sure you rewrite the copy constructor for this thing

namespace pele {

ATLJ::ATLJ(double sig, double eps, double Z)
    : m_eps(eps),
      m_sig(sig),
      m_Z(Z),
      m_ndim(3),
      m_natoms(3),
      ljpot(4 * eps * pow(sig, 6), 4 * eps * pow(sig, 12))

{}

double ATLJ::get_energy(const Array<double> &x) {
  double lj_energy = ljpot.get_energy(x);
  double at_energy = get_axilrod_teller_energy(x);
  return lj_energy + at_energy;
};

double ATLJ::get_axilrod_teller_energy(const Array<double> &x) {
  double energy = 0;
  Array<double> drij(m_natoms);
  Array<double> drjk(m_natoms);
  Array<double> drki(m_natoms);

  // Rewrite into a three pairwise loop for more atoms
  for (size_t i = 0; i < m_ndim; ++i) {
    drij[i] = x[i] - x[i + m_natoms];
    drjk[i] = x[i + m_natoms] - x[i + 2 * m_natoms];
    drki[i] = x[i + 2 * m_natoms] - x[i];
  }
  double rij = norm(drij);
  double rjk = norm(drjk);
  double rki = norm(drki);
  // note that this is slightly differently written, the - sign is taken outside
  double costhetaprod =
      -(3 * dot(drij, drjk) * dot(drjk, drki) * dot(drki, drij)) /
      pow((rij * rjk * rki), 2);
  energy += m_Z * (1 + costhetaprod) / (pow((rij * rjk * rki), 3));
  return energy;
}

}  // namespace pele