9#include "../Lattices/LatticeModule.h"
10#include <unsupported/Eigen/CXX11/Tensor>
14template <
int dim>
class Diff :
public Operator<Diff<dim>, dim> {
18 const Eigen::array<Eigen::Index, dim>
d;
20 explicit Diff(
const Eigen::array<Eigen::Index, dim> &d_,
21 const Eigen::Matrix<double, dim, dim> &A,
22 const Eigen::array<Eigen::Index, dim> &n_)
24 for (
const auto &order :
d)
28 template <
int dm = dim>
29 typename std::enable_if<dm == 1, void>::type
perform_op(
const double *x_in,
30 double *y_out)
const {
31 Eigen::TensorMap<const Eigen::Tensor<double, dm>> xReal(x_in,
n);
32 const Eigen::Tensor<dcomplex, dm> x = xReal.template cast<dcomplex>();
33 Eigen::TensorMap<Eigen::Tensor<double, dm>> y(y_out,
n);
37 for (
const auto &order :
d) {
38 totalOrder = totalOrder + order;
40 if (totalOrder == 0) {
46 Eigen::Tensor<dcomplex, dm> xhat(
n);
50 Eigen::Tensor<dcomplex, dm> d2fhat(
n);
54 for (
int i = 0; i <
n[0]; ++i) {
57 for (
int k = 0; k < dim; ++k) {
60 else if (
d[k] % 2 == 0)
61 r << (i <=
n[0] / 2 ? i : i -
n[0]);
63 r << (i ==
n[0] / 2 ? 0 : -
n[0] * (i / (
n[0] / 2)) + i);
68 d2fhat(i) = xhat(i) * factor;
72 Eigen::Tensor<dcomplex, dm> Lf(
n);
78 template <
int dm = dim>
79 typename std::enable_if<dm == 2, void>::type
perform_op(
const double *x_in,
80 double *y_out)
const {
81 Eigen::TensorMap<const Eigen::Tensor<double, 2>> xReal(x_in,
n);
82 const Eigen::Tensor<dcomplex, 2> x = xReal.cast<
dcomplex>();
83 Eigen::TensorMap<Eigen::Tensor<double, 2>> y(y_out,
n);
87 for (
const auto &order :
d) {
88 totalOrder = totalOrder + order;
90 if (totalOrder == 0) {
96 Eigen::Tensor<dcomplex, 2> xhat(
n);
100 Eigen::Tensor<dcomplex, 2> d2fhat(
n);
104 for (
int i = 0; i <
n[0]; ++i) {
105 for (
int j = 0; j <
n[1]; ++j) {
108 for (
int k = 0; k < dim; ++k) {
111 else if (
d[k] % 2 == 0)
112 r << (i <=
n[0] / 2 ? i : i -
n[0]), (j <=
n[1] / 2 ? j : j -
n[1]);
114 r << (i ==
n[0] / 2 ? 0 : -
n[0] * (i / (
n[0] / 2)) + i),
115 (j ==
n[1] / 2 ? 0 : -
n[1] * (j / (
n[1] / 2)) + j);
118 std::pow(-2.0 * M_PI *
dcomplex(0, 1) * r.cartesian()(k),
d[k]);
120 d2fhat(i, j) = xhat(i, j) * factor;
125 Eigen::Tensor<dcomplex, 2> Lf(
n);
131 template <
int dm = dim>
132 typename std::enable_if<dm == 3, void>::type
perform_op(
const double *x_in,
133 double *y_out)
const {
134 Eigen::TensorMap<const Eigen::Tensor<double, dm>> xReal(x_in,
n);
135 const Eigen::Tensor<dcomplex, dm> x = xReal.template cast<dcomplex>();
136 Eigen::TensorMap<Eigen::Tensor<double, dm>> y(y_out,
n);
140 for (
const auto &order :
d) {
141 totalOrder = totalOrder + order;
143 if (totalOrder == 0) {
149 Eigen::Tensor<dcomplex, dm> xhat(
n);
153 Eigen::Tensor<dcomplex, dm> d2fhat(
n);
157 for (
int i = 0; i <
n[0]; ++i) {
158 for (
int j = 0; j <
n[1]; ++j) {
159 for (
int k = 0; k <
n[2]; ++k) {
162 for (
int l = 0; l < dm; ++l) {
165 else if (
d[l] % 2 == 0)
166 r << (i <=
n[0] / 2 ? i : i -
n[0]),
167 (j <=
n[1] / 2 ? j : j -
n[1]),
168 (k <=
n[2] / 2 ? k : k -
n[2]);
170 r << (i ==
n[0] / 2 ? 0 : -
n[0] * (i / (
n[0] / 2)) + i),
171 (j ==
n[1] / 2 ? 0 : -
n[1] * (j / (
n[1] / 2)) + j),
172 (k ==
n[2] / 2 ? 0 : -
n[2] * (k / (
n[2] / 2)) + k);
175 std::pow(-2.0 * M_PI *
dcomplex(0, 1) * r.cartesian()(l),
d[l]);
177 d2fhat(i, j, k) = xhat(i, j, k) * factor;
183 Eigen::Tensor<dcomplex, dm> Lf(
n);
static void ifft(const Eigen::Tensor< dcomplex, 3 > &in, Eigen::Tensor< dcomplex, 3 > &out)
static void fft(const Eigen::Tensor< dcomplex, 3 > &in, Eigen::Tensor< dcomplex, 3 > &out)
Diff(const Eigen::array< Eigen::Index, dim > &d_, const Eigen::Matrix< double, dim, dim > &A, const Eigen::array< Eigen::Index, dim > &n_)
std::enable_if< dm==1, void >::type perform_op(const double *x_in, double *y_out) const
std::enable_if< dm==3, void >::type perform_op(const double *x_in, double *y_out) const
const Eigen::array< Eigen::Index, dim > d
std::enable_if< dm==2, void >::type perform_op(const double *x_in, double *y_out) const
std::complex< double > dcomplex
const Eigen::array< Eigen::Index, dim > n
VectorDimD cartesian() const