diff options
Diffstat (limited to 'transformation.hpp')
-rw-r--r-- | transformation.hpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/transformation.hpp b/transformation.hpp new file mode 100644 index 0000000..0731ec9 --- /dev/null +++ b/transformation.hpp @@ -0,0 +1,201 @@ +#pragma once + +#include <set> + +#include "random.hpp" +#include "spin.hpp" + +template <class U, int D, class R, class S> class Model; + +template <class U, int D, class R, class S> class Transformation { +public: + virtual std::set<Spin<U, D, S>*> current() const { return {NULL}; } + virtual std::set<Spin<U, D, S>*> toConsider() const { return {}; } + virtual double ΔE(const Spin<U, D, S>*) const { return 0; } + virtual Transformation* createNew(Spin<U, D, S>*) const { return new Transformation(); } + virtual void apply(){}; +}; + +template <class U, int D, class R, class S> +using Gen = std::function<Transformation<U, D, R, S>*(Model<U, D, R, S>&, Rng&)>; + +template <class U, int D, class R, class S> class SpinFlip : public Transformation<U, D, R, S> { +private: + Model<U, D, R, S>& M; + Spin<U, D, S>* sOld; + const R r; + Spin<U, D, S> sNew; + +public: + SpinFlip(Model<U, D, R, S>& M, const R& r, Spin<U, D, S>* s) : M(M), r(r) { + sOld = s; + sNew = r.act(*s); + } + + std::set<Spin<U, D, S>*> current() const override { return {sOld}; } + + std::set<Spin<U, D, S>*> toConsider() const override { + std::set<Spin<U, D, S>*> neighbors; + std::set<Spin<U, D, S>*> current_neighbors = M.dict.neighbors(sOld->x); + std::set<Spin<U, D, S>*> 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<U, D, S>* s) const override { + if (s == NULL) { + Spin<U, D, S> s0s_old = M.s0.inverse().act(*sOld); + Spin<U, D, S> 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<U, D, R, S>* createNew(Spin<U, D, S>* s) const override; + + void apply() override { + M.dict.remove(sOld); + *sOld = sNew; + M.dict.insert(sOld); + } +}; + +template <class U, int D, class R, class S> class PairFlip : public Transformation<U, D, R, S> { +private: + Model<U, D, R, S>& M; + Spin<U, D, S>* s1Old; + Spin<U, D, S>* s2Old; + const R r; + Spin<U, D, S> s1New; + Spin<U, D, S> s2New; + +public: + PairFlip(Model<U, D, R, S>& M, const R& r, Spin<U, D, S>* s1, Spin<U, D, S>* s2) : M(M), r(r) { + s1Old = s1; + s2Old = s2; + s1New = r.act(*s1); + s2New = r.act(*s2); + } + + std::set<Spin<U, D, S>*> current() const override { return {s1Old, s2Old}; } + + std::set<Spin<U, D, S>*> toConsider() const override { + std::set<Spin<U, D, S>*> neighbors; + std::set<Spin<U, D, S>*> current_neighbors_1 = M.dict.neighbors(s1Old->x); + std::set<Spin<U, D, S>*> current_neighbors_2 = M.dict.neighbors(s2Old->x); + std::set<Spin<U, D, S>*> new_neighbors_1 = M.dict.neighbors(s1New.x); + std::set<Spin<U, D, S>*> 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<U, D, S>* s) const override { + if (s == NULL) { + Spin<U, D, S> s0s1_old = M.s0.inverse().act(*s1Old); + Spin<U, D, S> s0s1_new = M.s0.inverse().act(s1New); + Spin<U, D, S> s0s2_old = M.s0.inverse().act(*s2Old); + Spin<U, D, S> 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<U, D, R, S>* createNew(Spin<double, D, S>* s) const; + Transformation<U, D, R, S>* createNew(Spin<signed, D, S>* s) const; + + 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 U, int D, class R, class S> class FieldFlip : public Transformation<U, D, R, S> { +private: + Model<U, D, R, S>& M; + const R r; + R s0New; + +public: + FieldFlip(Model<U, D, R, S>& M, const R& r) : M(M), r(r), s0New(r.act(M.s0)) {} + + std::set<Spin<U, D, S>*> toConsider() const override { + std::set<Spin<U, D, S>*> neighbors; + + for (Spin<U, D, S>* s : M.s) { + neighbors.insert(s); + } + + return neighbors; + } + + double ΔE(const Spin<U, D, S>* s) const override { + Spin<U, D, S> s0s_old = M.s0.inverse().act(*s); + Spin<U, D, S> s0s_new = s0New.inverse().act(*s); + return M.B(s0s_new) - M.B(s0s_old); + } + + Transformation<double, D, R, S>* createNew(Spin<double, D, S>* s) const { + return new SpinFlip<U, D, R, S>(M, r, s); + } + + Transformation<signed, D, R, S>* createNew(Spin<signed, D, S>* s) const { + Vector<signed, 2> v = r.act(*s).x; + std::set<Spin<U, D, S>*> on_site = M.dict.at(v); + if (on_site.empty()) { + return new SpinFlip<U, D, R, S>(M, r, s); + } else { + return new PairFlip<U, D, R, S>(M, r, s, *on_site.begin()); + } + } + + void apply() override { M.s0 = s0New; } +}; + +template <class U, int D, class R, class S> +Transformation<U, D, R, S>* SpinFlip<U, D, R, S>::createNew(Spin<U, D, S>* s) const { + if (s == NULL) { + return new FieldFlip<U, D, R, S>(M, r); + } else { + return new SpinFlip(M, r, s); + } +} + +template <class U, int D, class R, class S> +Transformation<U, D, R, S>* PairFlip<U, D, R, S>::createNew(Spin<double, D, S>* s) const { + if (s == NULL) { + return new FieldFlip<U, D, R, S>(M, r); + } else { + return new SpinFlip<U, D, R, S>(M, r, s); + } +} + +template <class U, int D, class R, class S> +Transformation<U, D, R, S>* PairFlip<U, D, R, S>::createNew(Spin<signed, D, S>* s) const { + if (s == NULL) { + return new FieldFlip<U, D, R, S>(M, r); + } else { + Vector<signed, 2> v = r.act(*s).x; + std::set<Spin<U, D, S>*> on_site = M.dict.at(v); + if (on_site.empty()) { + return new SpinFlip<U, D, R, S>(M, r, s); + } else { + return new PairFlip<U, D, R, S>(M, r, s, *on_site.begin()); + } + } +} |