#pragma once #include #include "random.hpp" #include "spin.hpp" template class Model; template class Transformation { public: Model& M; const R r; Transformation(Model& M, const R& r) : r(r), M(M) {} virtual std::set*> current() const { return {NULL}; } virtual std::set*> toConsider() const { return {}; } virtual double ΔE(const Spin*) const { return 0; } virtual Transformation* createNew(double T, std::set*>&, Spin*, Rng& rng) const { return new Transformation(M, r); } virtual void apply(){}; }; template using Gen = std::function*(Model&, Rng&)>; template class FieldFlip : public Transformation { private: R s0New; public: FieldFlip(Model& M, const R& r) : Transformation(M, r), s0New(r.act(M.s0)) {} std::set*> toConsider() const override { std::set*> neighbors; for (Spin* s : this->M.s) { neighbors.insert(s); } return neighbors; } double ΔE(const Spin* s) const override { Spin s0s_old = this->M.s0.inverse().act(*s); Spin s0s_new = s0New.inverse().act(*s); return this->M.B(s0s_new) - this->M.B(s0s_old); } Transformation* createNew(double T, std::set*>& cluster, Spin* s, Rng& rng) const override { return pairGenerator(this, T, cluster, s, rng); } void apply() override { this->M.s0 = s0New; } }; template class SpinFlip : public Transformation { private: Spin* sOld; Spin sNew; public: SpinFlip(Model& M, const R& r, Spin* s) : Transformation(M, r) { sOld = s; sNew = r.act(*s); } std::set*> current() const override { return {sOld}; } std::set*> toConsider() const override { std::set*> neighbors = {NULL}; std::set*> oldNeighbors = this->M.dict.neighbors(sOld->x); std::set*> newNeighbors = this->M.dict.neighbors(sNew.x); neighbors.insert(oldNeighbors.begin(), oldNeighbors.end()); neighbors.insert(newNeighbors.begin(), newNeighbors.end()); neighbors.erase(sOld); return neighbors; } double ΔE(const Spin* s) const override { if (s == NULL) { Spin s0s_old = this->M.s0.inverse().act(*sOld); Spin s0s_new = this->M.s0.inverse().act(sNew); return this->M.B(s0s_new) - this->M.B(s0s_old); } else { return this->M.Z(*sOld, *s) - this->M.Z(sNew, *s); } } Transformation* createNew(double T, std::set*>& cluster, Spin* s, Rng& rng) const override { if (s == NULL) { return new FieldFlip(this->M, this->r); } else { return pairGenerator(this, T, cluster, s, rng); } } void apply() override { this->M.dict.remove(sOld); *sOld = sNew; this->M.dict.insert(sOld); } }; template class PairFlip : public Transformation { private: Spin* s1Old; Spin* s2Old; Spin s1New; Spin s2New; public: PairFlip(Model& M, const R& r, Spin* s1, Spin* s2) : Transformation(M, 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 = {NULL}; std::set*> current_neighbors_1 = this->M.dict.neighbors(s1Old->x); std::set*> current_neighbors_2 = this->M.dict.neighbors(s2Old->x); std::set*> new_neighbors_1 = this->M.dict.neighbors(s1New.x); std::set*> new_neighbors_2 = this->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.erase(s1Old); neighbors.erase(s2Old); return neighbors; } double ΔE(const Spin* s) const override { if (s == NULL) { Spin s0s1_old = this->M.s0.inverse().act(*s1Old); Spin s0s1_new = this->M.s0.inverse().act(s1New); Spin s0s2_old = this->M.s0.inverse().act(*s2Old); Spin s0s2_new = this->M.s0.inverse().act(s2New); return this->M.B(s0s1_new) + this->M.B(s0s2_new) - this->M.B(s0s1_old) - this->M.B(s0s2_old); } else { return this->M.Z(*s1Old, *s) + this->M.Z(*s2Old, *s) - this->M.Z(s1New, *s) - this->M.Z(s2New, *s); } } Transformation* createNew(double T, std::set*>& cluster, Spin* s, Rng& rng) const override { if (s == NULL) { return new FieldFlip(this->M, this->r); } else { return pairGenerator(this, T, cluster, s, rng); } } void apply() override { this->M.dict.remove(s1Old); this->M.dict.remove(s2Old); *s1Old = s1New; *s2Old = s2New; this->M.dict.insert(s1Old); this->M.dict.insert(s2Old); } }; template Transformation* pairGenerator(const Transformation* tOld, double T, std::set*>& cluster, Spin* s, Rng& rng) { SpinFlip* t = new SpinFlip(tOld->M, tOld->r, s); Spin* sMax = NULL; double ΔEMax = 0.0; for (Spin* ss : t->toConsider()) { if (ss != NULL && ss != s && !cluster.contains(ss)) { double ΔE = t->ΔE(ss); if (ΔE > ΔEMax) { sMax = ss; ΔEMax = ΔE; } } } if (sMax == NULL || 1.0 - exp(-ΔEMax / T) < rng.uniform(0, 1) || cluster.contains(sMax)) { return t; } else { delete t; cluster.insert(sMax); return new PairFlip(tOld->M, tOld->r, s, sMax); } } template Transformation* pairGenerator(const Transformation* tOld, double T, std::set*>& cluster, Spin* s, Rng& rng) { Vector v = tOld->r.act(*s).x; std::set*> on_site = tOld->M.dict.at(v); if (on_site.empty()) { return new SpinFlip(tOld->M, tOld->r, s); } else { cluster.insert(*on_site.begin()); return new PairFlip(tOld->M, tOld->r, s, *on_site.begin()); } }