#pragma once #include #include #include #include #include #include "euclidean.hpp" #include "octree.hpp" #include "quantity.hpp" #include "spin.hpp" #include "random.hpp" #include "transformation.hpp" template class Model; template class measurement { public: virtual void pre_cluster(const Model&, unsigned, const R&){}; virtual void plain_bond_visited(const Model&, const Spin*, const Spin*, const Spin&, double){}; virtual void plain_site_transformed(const Model&, const Spin*, const Spin&){}; virtual void ghost_bond_visited(const Model&, const Spin&, const Spin&, double){}; virtual void ghost_site_transformed(const Model&, const R&){}; virtual void post_cluster(const Model&){}; }; template class Model { public: U L; R s0; std::vector*> s; Octree dict; std::function&, const Spin&)> Z; std::function&)> B; Rng rng; Model(U L, std::function&, const Spin&)> Z, std::function&)> B) : L(L), s0(L), Z(Z), B(B), rng(), dict(L, std::floor(L)) {} void step(double T, Transformation* t0, measurement& A) { std::queue*> queue; queue.push(t0); std::set*> visited; std::set*> fused; while (!queue.empty()) { Transformation* t = queue.front(); queue.pop(); std::set*> c = t->current(); if (!std::any_of(c.begin(), c.end(), [&visited](Spin* s) { return visited.contains(s); }) && !(c.size() == 1 && std::any_of(c.begin(), c.end(), [&fused](Spin* s) { return fused.contains(s); }))) { visited.insert(c.begin(), c.end()); fused.insert(c.begin(), c.end()); for (Spin* s : t->toConsider()) { if (!fused.contains(s)) { double ΔE = t->ΔE(s); if (ΔE > 0 && 1.0 - exp(-ΔE / T) > rng.uniform(0, 1)) { queue.push(t->createNew(T, fused, s, rng)); } } } t->apply(); } delete t; } } void resize(double T, double P) {} void wolff(double T, std::vector> gs, measurement& A, unsigned N) { for (unsigned i = 0; i < N; i++) { Gen& g = rng.pick(gs); Transformation *t = g(*this, rng); this->step(T, t, A); A.post_cluster(*this); } } };