Program Listing for File hessian_translations.hpp#
↰ Return to documentation for file (source/pele/hessian_translations.hpp)
#ifndef TRANSLATION_SYMMETRY_MATRICES_HPP
#define TRANSLATION_SYMMETRY_MATRICES_HPP
#include <Eigen/Dense>
#include <cstddef>
#include <pele/array.hpp>
#include <stdexcept>
#include <vector>
namespace pele {
inline void generate_2d_symmetries(size_t n_particles,
Eigen::MatrixXd &projector_x,
Eigen::MatrixXd &projector_y) {
projector_x.setZero();
projector_y.setZero();
if (projector_x.rows() != 2 * n_particles) {
throw std::logic_error("projector_x.rows() != 2 * n_particles");
}
if (projector_y.rows() != 2 * n_particles) {
throw std::logic_error("projector_y.rows() != 2 * n_particles");
}
for (size_t i = 0; i < n_particles * 2; i++) {
for (size_t j = i + 1; j < n_particles * 2; j++) {
if (i % 2 == 0 && j % 2 == 0) {
projector_x(i, j) = 1;
projector_x(j, i) = 1;
}
if (i % 2 == 1 && j % 2 == 1) {
projector_y(i, j) = 1;
projector_y(j, i) = 1;
}
}
}
}
inline void generate_3d_symmetries(size_t n_particles,
Eigen::MatrixXd &projector_x,
Eigen::MatrixXd &projector_y,
Eigen::MatrixXd &projector_z) {
projector_x.setZero();
projector_y.setZero();
projector_z.setZero();
if (projector_x.rows() != 3 * n_particles) {
throw std::logic_error("projector_x.rows() != 3 * n_particles");
}
if (projector_y.rows() != 3 * n_particles) {
throw std::logic_error("projector_y.rows() != 3 * n_particles");
}
if (projector_z.rows() != 3 * n_particles) {
throw std::logic_error("projector_z.rows() != 3 * n_particles");
}
for (size_t i = 0; i < n_particles * 3; i++) {
for (size_t j = i + 1; j < n_particles * 3; j++) {
if (i % 3 == 0 && j % 3 == 0) {
projector_x(i, j) = 1;
projector_x(j, i) = 1;
}
if (i % 3 == 1 && j % 3 == 1) {
projector_y(i, j) = 1;
projector_y(j, i) = 1;
}
if (i % 3 == 2 && j % 3 == 2) {
projector_z(i, j) = 1;
projector_z(j, i) = 1;
}
}
}
}
inline std::vector<Eigen::MatrixXd> get_symmetries(size_t n_particles,
size_t n_d) {
std::vector<Eigen::MatrixXd> symmetries;
if (n_d == 2) {
Eigen::MatrixXd projector_x, projector_y;
projector_x = Eigen::MatrixXd::Zero(2 * n_particles, 2 * n_particles);
projector_y = Eigen::MatrixXd::Zero(2 * n_particles, 2 * n_particles);
generate_2d_symmetries(n_particles, projector_x, projector_y);
symmetries.push_back(projector_x);
symmetries.push_back(projector_y);
} else if (n_d == 3) {
Eigen::MatrixXd projector_x, projector_y, projector_z;
projector_x = Eigen::MatrixXd::Zero(2 * n_particles, 2 * n_particles);
projector_y = Eigen::MatrixXd::Zero(2 * n_particles, 2 * n_particles);
generate_3d_symmetries(n_particles, projector_x, projector_y, projector_z);
symmetries.push_back(projector_x);
symmetries.push_back(projector_y);
symmetries.push_back(projector_z);
} else {
throw std::logic_error("n_d must be 2 or 3");
}
return symmetries;
}
inline void add_translation_offset_2d(Eigen::MatrixXd &hessian, double offset) {
// factor so that the added translation operators are unitary
double factor = 2.0 / hessian.rows();
offset = offset * factor;
for (size_t i = 0; i < hessian.rows(); ++i) {
for (size_t j = i + 1; j < hessian.cols(); ++j) {
if ((i % 2 == 0 && j % 2 == 0) || (i % 2 == 1 && j % 2 == 1)) {
hessian(i, j) += offset;
hessian(j, i) += offset;
}
}
}
hessian.diagonal().array() += offset;
}
inline void add_symmetry_offset(Eigen::MatrixXd &hessian,
const Array<double> &offset) {
for (size_t i = 0; i < hessian.rows(); ++i) {
for (size_t j = 0; j < hessian.cols(); ++j) {
hessian(i, j) += offset[i * hessian.rows() + j];
}
}
}
} // namespace pele
#endif // TRANSLATION_SYMMETRY_MATRICES_HPP