#pragma once #include #include #include #include #include #include "pcg-cpp/include/pcg_random.hpp" #include "randutils/randutils.hpp" #include "euclidean.hpp" #include "octree.hpp" #include "quantity.hpp" #include "spin.hpp" using Rng = randutils::random_generator; template class Model; template class measurement { public: virtual void pre_cluster(const Model&, unsigned, const R&){}; virtual void plain_bond_visited(const Model&, const Spin*, const Spin*, const Spin&, double){}; virtual void plain_site_transformed(const Model&, const Spin*, const Spin&){}; virtual void ghost_bond_visited(const Model&, const Spin&, const Spin&, double){}; virtual void ghost_site_transformed(const Model&, const R&){}; virtual void post_cluster(const Model&){}; }; template class Transformation { public: virtual std::set*> current() const {return {NULL};} virtual std::set*> toConsider() const {return {};} virtual double ΔE(const Spin*) const {return 0;} virtual Transformation* createNew(Spin*) const {return new Transformation();} virtual void apply(); }; template using Gen = std::function*(Model&, Rng&)>; template class SpinFlip : public Transformation { private: Model& M; Spin& sOld; const R r; Spin sNew; public: SpinFlip(Model& M, const R& r, Spin& s) : M(M), r(r), sOld(s) { sNew = r.act(s); } std::set*> current() const override { return {&sOld}; } std::set*> toConsider() const override { std::set*> neighbors; std::set*> current_neighbors = M.dict.neighbors(sOld.x); std::set*> new_neighbors = M.dict.neighbors(sNew.x); neighbors.insert(current_neighbors.begin(), current_neighbors.end()); neighbors.insert(new_neighbors.begin(), new_neighbors.end()); neighbors.insert(NULL); return neighbors; } double ΔE(const Spin* s) const override { if (s == NULL) { Spin s0s_old = M.s0.inverse().act(sOld); Spin s0s_new = M.s0.inverse().act(sNew); return M.B(s0s_new) - M.B(s0s_old); } else { return M.Z(sOld, *s) - M.Z(sNew, *s); } } Transformation* createNew(Spin* s) const override; void apply() override { M.dict.remove(&sOld); sOld = sNew; M.dict.insert(&sOld); } }; template class PairFlip : public Transformation { private: Model& M; Spin& s1Old; Spin& s2Old; const R r; Spin s1New; Spin s2New; public: PairFlip(Model& M, const R& r, Spin& s1, Spin& s2) : M(M), r(r), s1Old(s1), s2Old(s2) { s1New = r.act(s1); s2New = r.act(s2); } std::set*> current() const override { return {&s1Old, &s2Old}; } std::set*> toConsider() const override { std::set*> neighbors; std::set*> current_neighbors_1 = M.dict.neighbors(s1Old.x); std::set*> current_neighbors_2 = M.dict.neighbors(s2Old.x); std::set*> new_neighbors_1 = M.dict.neighbors(s1New.x); std::set*> new_neighbors_2 = M.dict.neighbors(s2New.x); neighbors.insert(current_neighbors_1.begin(), current_neighbors_1.end()); neighbors.insert(current_neighbors_2.begin(), current_neighbors_2.end()); neighbors.insert(new_neighbors_1.begin(), new_neighbors_1.end()); neighbors.insert(new_neighbors_2.begin(), new_neighbors_2.end()); neighbors.insert(NULL); return neighbors; } double ΔE(const Spin* s) const override { if (s == NULL) { Spin s0s1_old = M.s0.inverse().act(s1Old); Spin s0s1_new = M.s0.inverse().act(s1New); Spin s0s2_old = M.s0.inverse().act(s2Old); Spin s0s2_new = M.s0.inverse().act(s2New); return M.B(s0s1_new) + M.B(s0s2_new) - M.B(s0s1_old) - M.B(s0s2_old); } else { return M.Z(s1Old, *s) + M.Z(s2Old, *s) - M.Z(s1New, *s) - M.Z(s2New, *s); } } Transformation* createNew(Spin* s) const override; void apply() override { M.dict.remove(&s1Old); M.dict.remove(&s2Old); s1Old = s1New; s2Old = s2New; M.dict.insert(&s1Old); M.dict.insert(&s2Old); } }; template class FieldFlip : public Transformation { private: Model& M; const R r; R s0New; public: FieldFlip(Model& M, const R& r) : M(M), r(r), s0New(r.act(M.s0)) {} std::set*> toConsider() const override { std::set*> neighbors; for (Spin& s : M.s) { neighbors.insert(&s); } return neighbors; } double ΔE(const Spin* s) const override { Spin s0s_old = M.s0.inverse().act(*s); Spin s0s_new = s0New.inverse().act(*s); return M.B(s0s_new) - M.B(s0s_old); } Transformation* createNew(Spin* s) const override { return new SpinFlip(M, r, *s); } void apply() override { M.s0 = s0New; } }; template Transformation* SpinFlip::createNew(Spin* s) const { if (s == NULL) { return new FieldFlip(M, r); } else { return new SpinFlip(M, r, *s); } } template Transformation* PairFlip::createNew(Spin* s) const { if (s == NULL) { return new FieldFlip(M, r); } else { return new SpinFlip(M, r, *s); } } template class Model { public: U L; R s0; std::vector> s; Octree dict; std::function&, const Spin&)> Z; std::function&)> B; Rng rng; Model(U L, std::function&, const Spin&)> Z, std::function&)> B) : L(L), s0(L), Z(Z), B(B), rng(), dict(L, std::floor(L)) {} void step(double T, Transformation* t0, measurement& A) { std::queue*> queue; queue.push(t0); std::set*> visited; while (!queue.empty()) { Transformation* t = queue.front(); queue.pop(); std::set*> c = t->current(); if (!std::any_of(c.begin(), c.end(), [&visited](Spin* s) { return visited.contains(s); })) { visited.insert(c.begin(), c.end()); for (Spin* s : t->toConsider()) { double ΔE = t->ΔE(s); if (ΔE > 0 && 1.0 - exp(-ΔE / T) > rng.uniform(0, 1)) { queue.push(t->createNew(s)); } } t->apply(); } delete t; } } void resize(double T, double P) {} void wolff(double T, std::vector> gs, measurement& A, unsigned N) { for (unsigned i = 0; i < N; i++) { Gen& g = rng.pick(gs); Transformation *t = g(*this, rng); this->step(T, t, A); A.post_cluster(*this); } } };