From c616bc12f23162b6b1714ea936f4a2dafd0780a3 Mon Sep 17 00:00:00 2001 From: Jaron Kent-Dobias Date: Fri, 12 Nov 2021 11:51:54 +0100 Subject: Starting implementing collective moves. --- spheres.hpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 18 deletions(-) (limited to 'spheres.hpp') diff --git a/spheres.hpp b/spheres.hpp index 6dd5b04..161ef9c 100644 --- a/spheres.hpp +++ b/spheres.hpp @@ -177,9 +177,57 @@ public: } }; +template T> class Move { +public: + const Euclidean g; + std::vector ps; + std::vector> xNews; + + Move(const Euclidean& g, std::vector ps) : g(g), ps(ps) { + xNews.reserve(ps.size()); + for (T* p : ps) { + xNews.push_back(g.act((Position)p->x)); + } + } + + void insert(T* p) { + ps.push_back(p); + xNews.push_back(g.act(p->x)); + } + + bool anyMarked() const { + for (const T* p : ps) { + if (p->m) { + return true; + } + } + + return false; + } + + unsigned size() const { + return ps.size(); + } + + double ΔE(const T& n) const { + double e = 0; + + for (unsigned i = 0; i < ps.size(); i++) { + if (&n == ps[i]) { + return 0; + } else { + e += n.U(xNews[i], ps[i]->r) - n.U(ps[i]->x, ps[i]->r); + } + } + + return e; + } +}; + + template T> class Model { private: - bool metropolisAccept(double β, double ΔE, Rng& r) const { + bool metropolisAccept(double β, double ΔE, Rng& r, double a = 1.0) const { return ΔE < 0 || exp(-β * ΔE) > r.uniform(0.0, 1.0); } @@ -208,6 +256,13 @@ public: p.x = x; } + void execute(Move& m) { + for (unsigned i = 0; i < m.size(); i++) { + move(*(m.ps[i]), m.xNews[i]); + m.ps[i]->m = true; + } + } + bool move(double β, T& p, const Vector& Δx, Rng& r) { Position xNew = p.x + Δx; double ΔE = 0; @@ -270,37 +325,56 @@ public: return move(β, r.pick(particles), Δx, r); } - unsigned clusterFlip(double β, const Euclidean& R, T& p0, Rng& r) { + unsigned clusterFlip(double β, const Euclidean& R, Move& m0, Rng& r) { unsigned n = 0; - std::queue q; - q.push(&p0); + std::queue> q; + q.push(m0); while (!q.empty()) { - T* p = q.front(); + Move m = q.front(); q.pop(); - if (!p->m) { - p->m = true; - Position xNew = R.act(p->x); + if (!m.anyMarked()) { + std::set neighbors = {}; + for (unsigned i = 0; i < m.ps.size(); i++) { + std::set pNeighbors = nl.neighborsOf(m.ps[i]->x); + std::set pNeighborsNew = nl.neighborsOf(m.xNews[i]); + neighbors.insert(pNeighbors.begin(), pNeighbors.end()); + neighbors.insert(pNeighborsNew.begin(), pNeighborsNew.end()); + } + double ΔEmax = 0; + T* pMax = NULL; - for (T* neighbor : nl.neighborsOf(xNew)) { + for (T* neighbor : neighbors) { if (!neighbor->m) { - double ΔE = neighbor->U(xNew, p->r) - neighbor->U(p->x, p->r); + double ΔE = m.ΔE(*neighbor); + if (ΔE > ΔEmax) { + ΔEmax = ΔE; + pMax = neighbor; + } + } + } + + if (pMax != NULL) { + if (1 - 1e2 * exp(-β * ΔEmax) > r.uniform(0.0, 1.0)) { + m.insert(pMax); + } + } + + for (T* neighbor : neighbors) { + if (!neighbor->m) { + double ΔE = m.ΔE(*neighbor); if (1 - exp(-β * ΔE) > r.uniform(0.0, 1.0)) { - q.push(neighbor); + q.push(Move(R, {neighbor})); } } } - move(*p, xNew); - n++; + execute(m); + n += m.size();; } } - for (T& p : particles) { - p.m = false; - } - if (n > particles.size() / 2) { orientation = R.act(orientation); } @@ -325,7 +399,9 @@ public: Euclidean<2> g(t - mat * t, mat); - return clusterFlip(β, g, s1, r); + Move m(g, {&s1, &s2}); + + return clusterFlip(β, g, m, r); } unsigned randomClusterSwap(double β, Rng& r) { -- cgit v1.2.3-54-g00ecf