#include "space_wolff.hpp" template std::function&, const Spin&)> zSpheres(double a, double k) { return [a, k](const Spin& s1, const Spin& s2) -> double { Vector d = s1.x - s2.x; double σ = s1.s + s2.s; double δ = σ - sqrt(d.transpose() * d); if (δ > -a * σ) { return 0.5 * k * (2 * pow(a * σ, 2) - pow(δ, 2)); } else if (δ > -2 * a * σ) { return 0.5 * k * pow(δ + 2 * a * σ, 2); } else { return 0; } }; } template std::function)> bCenter(double H) { return [H](Spin s) -> double { return H * s.x.norm(); }; } template Euclidean flipAround(double θ, Vector& t₀) { Matrix m; m(0, 0) = -cos(2 * θ); m(1, 1) = cos(2 * θ); m(0, 1) = -2 * cos(θ) * sin(θ); m(1, 0) = -2 * cos(θ) * sin(θ); return Euclidean(t₀ - m * t₀, m); } template Gen, S> nudgeGen(double ε) { return [ε](Model, S>& M, Rng& rng) -> Transformation, S>* { double θ = rng.uniform((double)0.0, 2 * M_PI); Spin* s = rng.pick(M.s); Vector t = s->x; for (unsigned j = 0; j < D; j++) { t(j) += rng.variate(0.0, ε); } return new SpinFlip, S>(M, flipAround(θ, t), s); }; } template Gen, S> swapGen(double ε) { return [ε](Model, S>& M, Rng& rng) -> Transformation, S>* { Spin* s1 = rng.pick(M.s); Spin* s2 = rng.pick(M.s); while (s1 == s2) { s2 = rng.pick(M.s); } Vector t1 = s1->x; Vector t2 = s2->x; Vector t12 = t1 - t2; Vector t = (t1 + t2) / 2; double θ = atan2(t12(1), t12(0)) + rng.variate(0.0, ε) / t12.norm(); return new PairFlip, S>(M, flipAround(θ, t), s1, s2); }; } template Gen, S> accrossGen(double ε) { return [ε](Model, S>& M, Rng& rng) -> Transformation, S>* { Spin* s1 = rng.pick(M.s); Spin* s2 = rng.pick(M.s); while (s1 == s2) { s2 = rng.pick(M.s); } Vector t1 = s1->x; Vector t2 = s2->x; Vector t12 = t1 - t2; Vector t = t2; double θ = atan2(t12(1), t12(0)) + rng.variate(0.0, ε) / t12.norm(); return new SpinFlip, S>(M, flipAround(θ, t), s1); }; } template Gen, S> centerGen(double ε) { return [ε](Model, S>& M, Rng& rng) -> Transformation, S>* { double θ = rng.uniform((double)0.0, 2 * M_PI); Vector t = M.s0.t; for (unsigned j = 0; j < D; j++) { t(j) += rng.variate(0.0, ε); } Spin* s = rng.pick(M.s); return new SpinFlip, S>(M, flipAround(θ, t), s); }; }