summaryrefslogtreecommitdiff
path: root/transformation.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'transformation.hpp')
-rw-r--r--transformation.hpp201
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());
+ }
+ }
+}