“Know how to solve every problem that has been solved.” “What I cannot create, I do not understand.” — Richard Feynman
cpp 77 lines · 2.1 KB
#include "qc/integrals.hpp"

#include "qc/cart_int.hpp"

namespace qc {

double MolecularIntegrals::eri_index(std::size_t i, std::size_t j, std::size_t k,
                                     std::size_t l) const {
  const std::size_t n = S.rows();
  return eri[(((i * n + j) * n + k) * n + l)];
}

MolecularIntegrals compute_integrals(const Basis& basis,
                                     const std::vector<Atom>& atoms) {
  const std::size_t n = basis.n_ao();
  MolecularIntegrals out;
  out.S.resize(n, n, 0.0);
  out.T.resize(n, n, 0.0);
  out.V.resize(n, n, 0.0);
  out.eri.assign(n * n * n * n, 0.0);

  for (std::size_t A = 0; A < n; ++A) {
    for (std::size_t B = 0; B < n; ++B) {
      double s = 0.0;
      double t = 0.0;
      double v = 0.0;
      for (const auto& pa : basis.aos[A].prims) {
        for (const auto& pb : basis.aos[B].prims) {
          s += cart_overlap(pa, pb);
          t += cart_kinetic(pa, pb);
          for (const auto& atom : atoms) {
            v += cart_nuclear(pa, pb, atom);
          }
        }
      }
      out.S(A, B) = s;
      out.T(A, B) = t;
      out.V(A, B) = v;
    }
  }

  auto eri_ptr = [&](std::size_t i, std::size_t j, std::size_t k,
                     std::size_t l) -> double& {
    return out.eri[(((i * n + j) * n + k) * n + l)];
  };

  for (std::size_t i = 0; i < n; ++i) {
    for (std::size_t j = 0; j < n; ++j) {
      for (std::size_t k = 0; k < n; ++k) {
        for (std::size_t l = 0; l < n; ++l) {
          double g = 0.0;
          for (const auto& pi : basis.aos[i].prims) {
            for (const auto& pj : basis.aos[j].prims) {
              for (const auto& pk : basis.aos[k].prims) {
                for (const auto& pl : basis.aos[l].prims) {
                  g += cart_eri(pi, pj, pk, pl);
                }
              }
            }
          }
          eri_ptr(i, j, k, l) = g;
          eri_ptr(i, j, l, k) = g;
          eri_ptr(j, i, k, l) = g;
          eri_ptr(j, i, l, k) = g;
          eri_ptr(k, l, i, j) = g;
          eri_ptr(k, l, j, i) = g;
          eri_ptr(l, k, i, j) = g;
          eri_ptr(l, k, j, i) = g;
        }
      }
    }
  }

  return out;
}

}  // namespace qc