#pragma once #include #include #include #include "types.hpp" #include "factorial.hpp" using Vector = Eigen::Matrix; using Matrix = Eigen::Matrix; template using Tensor = Eigen::Tensor; template using constTensor = Eigen::Tensor; template Tensor

initializeJHelper(unsigned N, unsigned M, std::index_sequence) { std::array Ns; std::fill_n(Ns.begin(), p, N); Ns[p-1] = M; return Tensor

(std::get(Ns)...); } template Tensor

initializeJ(unsigned N, unsigned M) { return initializeJHelper

(N, M, std::make_index_sequence

()); } template void setJHelper(Tensor

& J, const std::array& ind, Real val, std::index_sequence) { J(std::get(ind)...) = val; } template void setJ(Tensor

& J, std::array ind, Real val) { setJHelper

(J, ind, val, std::make_index_sequence

()); } template Real getJHelper(const Tensor

& J, const std::array& ind, std::index_sequence) { return J(std::get(ind)...); } template Real getJ(const Tensor

& J, const std::array& ind) { return getJHelper

(J, ind, std::make_index_sequence

()); } template void iterateOverHelper(Tensor

& J, std::function&, std::array)>& f, unsigned l, std::array is) { if (l == 0) { f(J, is); } else { for (unsigned i = 0; i < J.dimension(p - l); i++) { std::array js = is; js[p - l] = i; iterateOverHelper

(J, f, l - 1, js); } } } template void iterateOver(Tensor

& J, std::function&, std::array)>& f) { std::array is; iterateOverHelper

(J, f, p, is); } template Tensor

generateCouplings(unsigned N, unsigned M, Distribution d, Generator& r) { Tensor

J = initializeJ

(N, M); std::function&, std::array)> setRandom = [&d, &r] (Tensor

& JJ, std::array ind) { setJ

(JJ, ind, d(r)); }; iterateOver

(J, setRandom); return J; } template Tensor

generateRealPSpinCouplings(unsigned N, unsigned M, Generator& r) { Real σp = sqrt(factorial(p-1) / ((Real)2 * pow(N, p - 1))); return generateCouplings

(N, M, std::normal_distribution(0, σp), r); } Tensor<3> contractDown(const Tensor<3>& J, const Vector& z) { return J; } const std::array, 1> ip00 = {Eigen::IndexPair(0, 0)}; const std::array, 1> ip20 = {Eigen::IndexPair(2, 0)}; template Tensor<3> contractDown(const Tensor& J, const Vector& z) { Tensor<1> zT = Eigen::TensorMap>(z.data(), {z.size()}); Tensor Jz = J.contract(zT, ip00); return contractDown(Jz, z); }