From 70b13f405bf861dd16e0ddb963293e5546599b3d Mon Sep 17 00:00:00 2001 From: Jaron Kent-Dobias Date: Fri, 25 Jun 2021 10:57:46 +0200 Subject: Partial progress towards merging BM model into global objects. --- glass.hpp | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 205 insertions(+), 4 deletions(-) (limited to 'glass.hpp') diff --git a/glass.hpp b/glass.hpp index 64fe8b7..d313ced 100644 --- a/glass.hpp +++ b/glass.hpp @@ -180,6 +180,7 @@ public: const unsigned L; unsigned N; std::vector> vertices; + Transformation orientation; unsigned vectorToIndex(const Vector& x) const { unsigned i = 0; @@ -197,7 +198,7 @@ public: return x; } - System(unsigned L, unsigned N) : L(L), N(N), vertices(iPow(L, D)) { + System(unsigned L) : L(L), N(0), vertices(iPow(L, D)), orientation(L) { for (unsigned i = 0; i < iPow(L, D); i++) { vertices[i].position = indexToVector(i); vertices[i].initialPosition = vertices[i].position; @@ -216,8 +217,14 @@ public: } } + unsigned size() const { return vertices.size(); } + double density() const { return N / pow(L, D); } + unsigned maxOccupation() const { + return iPow(L, D); + } + void setInitialPosition() { for (Vertex& v : vertices) { v.initialPosition = v.position; @@ -240,7 +247,7 @@ public: } }; -template class FiniteEnergySystem : public System { +template class SoftSystem : public System { public: using System::System; @@ -326,7 +333,7 @@ public: bool dry = false) { std::queue>, 2>> q; Vector x0New = R.apply(v0.position); - Vertex& v0New = this->vertices[this->vectorToIndex(x0New)]; + Vertex& v0New = SoftSystem::vertices[SoftSystem::vectorToIndex(x0New)]; q.push({v0, v0New}); unsigned n = 0; @@ -346,7 +353,7 @@ public: Vertex& vn = e.neighbor; Vector xnNew = R.apply(vn.position); - Vertex& vnNew = this->vertices[this->vectorToIndex(xnNew)]; + Vertex& vnNew = SoftSystem::vertices[SoftSystem::vectorToIndex(xnNew)]; if (!vn.marked && !vnNew.marked) { double E0 = pairEnergy(v.state, vn.state) + pairEnergy(vNew.state, vnNew.state); @@ -393,3 +400,197 @@ public: } }; +template class HardSystem : public System { +public: + + HardSystem(unsigned L) : System(L) {} + + virtual std::list>> overlaps(Vertex&, const S&, + bool = false) { return {}; } + + bool insert(Vertex& v, const S& s) { + if (overlaps(v, s).empty()) { + v.state = s; + HardSystem::N++; + return true; + } else { + return false; + } + } + + bool tryDeletion(Vertex& v) { + if (v.empty()) { + return false; + } else { + v.state.remove(); + HardSystem::N--; + return true; + } + } + + bool tryRandomMove(Rng& r) { + Vertex& v = r.pick(HardSystem::vertices); + S oldState = v.state; + + if (!tryDeletion(v)) { + return false; + } + + if (1.0 / (2.0 * D) > r.uniform(0.0, 1.0)) { + for (HalfEdge& e : v.adjacentEdges) { + if (1 == e.Δx.dot(oldState)) { + if (insert(e.neighbor, oldState.flip())) { + return true; + } + break; + } + } + } else { + S newState(r); + while (newState == oldState) { + newState = S(r); + } + if (insert(v, newState)) { + return true; + } + } + v.state = oldState; + HardSystem::N++; + return false; + } + + bool trySwap(Vertex& v1, Vertex& v2) { + if (overlaps(v1, v2.state, true).size() == 0 && overlaps(v2, v1.state, true).size() == 0) { + std::swap(v1.state, v2.state); + return true; + } else { + return false; + } + } + + bool tryRandomSwap(Rng& r) { + Vertex& v1 = r.pick(HardSystem::vertices); + Vertex& v2 = r.pick(HardSystem::vertices); + + return trySwap(v1, v2); + } + + + bool compatible() { + for (Vertex& v : HardSystem::vertices) { + if (overlaps(v, v.state, true).size() > 0) { + return false; + } + } + + return true; + } + + void sweepGrandCanonical(double z, Rng& r) { + for (unsigned i = 0; i < iPow(HardSystem::L, D); i++) { + if (0.5 < r.uniform(0.0, 1.0)) { + double pIns = HardSystem::maxOccupation() * z / (HardSystem::N + 1); + + if (pIns > r.uniform(0.0, 1.0)) { + while (true) { + Vertex& v = r.pick(HardSystem::vertices); + if (v.empty()) { + insert(v, S(r)); + break; + } + } + } + } else { + + double pDel = HardSystem::N / (z * HardSystem::maxOccupation()); + + if (pDel > r.uniform(0.0, 1.0)) { + tryDeletion(r.pick(HardSystem::vertices)); + } + } + + tryRandomMove(r); + } + } + + void sweepLocal(Rng& r) { + for (unsigned i = 0; i < iPow(HardSystem::L, D); i++) { + tryRandomMove(r); + } + } + + void sweepSwap(Rng& r) { + for (unsigned i = 0; i < iPow(HardSystem::L, D); i++) { + tryRandomSwap(r); + } + } + + unsigned flipCluster(const Transformation& R, Vertex& v0, Rng& r, bool dry = false) { + std::queue>> q; + q.push(v0); + + unsigned n = 0; + + while (!q.empty()) { + Vertex& v = q.front(); + q.pop(); + + if (!v.marked) { + Vector xNew = R.apply(v.position); + Vertex& vNew = HardSystem::vertices[HardSystem::vectorToIndex(xNew)]; + + v.marked = true; + vNew.marked = true; + + S s = R.apply(v.state); + S sNew = R.apply(vNew.state); + + std::list>> overlaps1 = overlaps(vNew, s, true); + std::list>> overlaps2 = overlaps(v, sNew, true); + overlaps1.splice(overlaps1.begin(), overlaps2); + + for (Vertex& vn : overlaps1) { + if (!vn.marked) { + q.push(vn); + } + } + + if (!dry) { + v.state = sNew; + vNew.state = s; + } + + n += 1; + } + } + + return n; + } + + void swendsenWang(const Transformation& R, Rng& r) { + for (Vertex& v : HardSystem::vertices) { + if (!v.marked) { + bool dry = 0.5 < r.uniform(0.0, 1.0); + unsigned n = flipCluster(R, v, r, dry); + if (n > pow(HardSystem::L, D) / 4 && !dry) { + orientation = R.apply(orientation); + } + } + } + + for (Vertex& v : HardSystem::vertices) { + v.marked = false; + } + } + + int overlap(const System& s) const { + int o = 0; + + for (unsigned i = 0; i < HardSystem::vertices.size(); i++) { + S s2 = orientation.apply(s.vertices[HardSystem::vectorToIndex(orientation.inverse().apply(HardSystem::indexToVector(i)))].state); + o += HardSystem::vertices[i].state.dot(s2); + } + + return o; + } +}; -- cgit v1.2.3-54-g00ecf