summaryrefslogtreecommitdiff
path: root/ising.hpp
blob: 6f140be4ac8595d080b6bf839636d6aaa9f9c723 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

#include "smiley.hpp"
#include "space_wolff.hpp"
#include "torus_symmetries.hpp"

const unsigned D = 2;
typedef Model<signed, D, TorusGroup<signed, D>, signed> isingModel;
typedef Spin<signed, D, signed> isingSpin;

std::function<double(const isingSpin&, const isingSpin&)> isingZ(unsigned L) {
  return [L](const isingSpin& s1, const isingSpin& s2) -> double {
    bool old_one_one = false;
    bool old_many_ones = false;
    bool old_any_two = false;

    Vector<signed, D> old_diff = diff<signed, D>(L, s1.x, s2.x);

    for (unsigned i = 0; i < D; i++) {
      if (old_diff(i) == 1 && !old_one_one) {
        old_one_one = true;
      } else if (old_diff(i) == 1 && old_one_one) {
        old_many_ones = true;
      } else if (old_diff(i) > 1) {
        old_any_two = true;
      }
    }

    bool were_on_someone = !old_one_one && !old_any_two;
    bool were_nearest_neighbors = old_one_one && !old_many_ones && !old_any_two;

    if (were_on_someone) {
      return -std::numeric_limits<double>::infinity();
      ;
    } else if (were_nearest_neighbors) {
      return s1.s * s2.s;
    } else {
      return 0.0;
    }
  };
}

std::function<double(isingSpin)> isingBFace(unsigned L, double H) {
  return [L, H](const isingSpin& s) -> double {
    return H * s.s * smiley[15 - s.x(1) * 16 / L][s.x(0) * 16 / L];
  };
}

std::function<double(isingSpin)> isingBMod(unsigned L, unsigned mod, double H) {
  return [mod, L, H](const isingSpin& s) -> double {
    return H * s.s * sin(s.x(0) * mod * 2 * M_PI / L);
  };
}

Gen<signed, D, TorusGroup<signed, D>, signed> isingGen(unsigned L) {
  std::vector<Vector<signed, 2>> torusVectors = torus_vecs<signed, 2>(L);
  std::vector<Matrix<signed, 2>> torusMatrices = torus_mats<signed, 2>();
  return [L, torusVectors,
          torusMatrices](Model<signed, D, TorusGroup<signed, D>, signed>& M,
                         Rng& r) -> Transformation<signed, D, TorusGroup<signed, D>, signed>* {
    Matrix<signed, 2> m;
    Vector<signed, 2> t;

    m = r.pick(torusMatrices);
    t(0) = r.uniform<signed>(0, L);
    t(1) = r.uniform<signed>(0, L);
    t = t - m * t;

    TorusGroup<signed, 2> g = TorusGroup<signed, 2>({(signed)L, t, m});

    Spin<signed, 2, signed>* ss = r.pick(M.s);
    Spin<signed, 2, signed> s2 = g.act(*ss);

    while (ss->x(0) == s2.x(0) && ss->x(1) == s2.x(1)) {
      ss = r.pick(M.s);
      s2 = g.act(*ss);
    }

    std::set<Spin<signed, 2, signed>*> s2s = M.dict.at(s2.x);

    if (s2s.empty()) {
      return new SpinFlip<signed, 2, TorusGroup<signed, 2>, signed>(M, g, ss);
    } else {
      return new PairFlip<signed, 2, TorusGroup<signed, 2>, signed>(M, g, ss, *s2s.begin());
    }
  };
}

void isingPopulate(isingModel& m, unsigned L, double pop, double mag) {
  Rng rng;

  for (unsigned i = 0; i < L; i++) {
    for (unsigned j = 0; j < L; j++) {
      if (rng.uniform<double>(0, 1) < pop) {
      Spin<signed, D, signed>* ss = new Spin<signed, D, signed>();
      ss->x = {i, j};
      if (rng.uniform<double>(0, 1) < mag) {
        ss->s = 1;
      } else {
        ss->s = -1;
      }
      m.s.push_back(ss);
      m.dict.insert(ss);
      }
    }
  }
}