#pragma once #include #include #include #include "matrix.hpp" #include "vector.hpp" #include "euclidean.hpp" #include "transformation.hpp" template void one_sequences(std::list>& sequences, unsigned level) { if (level > 0) { unsigned new_level = level - 1; unsigned old_length = sequences.size(); for (std::array& sequence : sequences) { std::array new_sequence = sequence; new_sequence[new_level] = -1; sequences.push_front(new_sequence); } one_sequences(sequences, new_level); } } template std::vector> torus_vecs(U L) { std::vector> vecs; std::array ini_sequence; ini_sequence.fill(1); std::list> sequences; sequences.push_back(ini_sequence); one_sequences(sequences, D); sequences.pop_front(); // don't want the identity matrix! for (std::array sequence : sequences) { Vector v; for (unsigned i = 0; i < D; i++) { if (sequence[i] == 1) { v(i) = 0; } else { v(i) = L / 2; } } vecs.push_back(v); } return vecs; } template std::vector> torus_mats() { std::vector> mats; std::array ini_sequence; ini_sequence.fill(1); std::list> sequences; sequences.push_back(ini_sequence); one_sequences(sequences, D); sequences.pop_back(); // don't want the identity matrix! for (std::array sequence : sequences) { Matrix m; for (unsigned i = 0; i < D; i++) { for (unsigned j = 0; j < D; j++) { if (i == j) { m(i, j) = sequence[i]; } else { m(i, j) = 0; } } } mats.push_back(m); } for (unsigned i = 0; i < D; i++) { for (unsigned j = 0; j < D; j++) { if (i != j) { Matrix m; for (unsigned k = 0; k < D; k++) { for (unsigned l = 0; l < D; l++) { if ((k == i && l == j) || (k == j && l == i)) { if (i < j) { m(k, l) = 1; } else { m(k, l) = -1; } } else { m(k, l) = 0; } } } mats.push_back(m); } } } return mats; } template Gen, S> uniformGenTorus(double L) { std::vector> torusVectors = torus_vecs(L); std::vector> torusMatrices = torus_mats(); return [L, torusVectors, torusMatrices](Model, S>& M, Rng& r) -> Transformation, S>* { Matrix m = r.pick(torusMatrices); Vector t; for (unsigned i = 0; i < D; i++) { t(i) = r.uniform(0, L); } TorusGroup g = TorusGroup({(double)L, t - m * t, m}); Spin* ss = r.pick(M.s); return new SpinFlip, S>(M, g, ss); }; }