summaryrefslogtreecommitdiff
path: root/lib/include/wolff/state.hpp
blob: e7c0ac376ae064a7696a6ff3e128766ba654fbbe (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

#pragma once

#include <functional>
#include <vector>

#include "types.h"
#include "graph.hpp"

template <class R_t, class X_t>
class state_t {
  private:
    // updating fourier terms F requires many cos and sin calls, faster to do it beforehand.
    std::vector<std::vector<double>> precomputed_cos;
    std::vector<std::vector<double>> precomputed_sin;
  public:
    D_t D;
    L_t L;
    v_t nv; // the number of vertices in the lattice
    v_t ne; // the number of edges in the lattice
    graph_t g; // the graph defining the lattice without ghost
    double T; // the temperature
    std::vector<X_t> spins; // the state of the ordinary spins
#ifndef NOFIELD
    R_t R; // the current state of the ghost site
#endif
    double E; // the system's total energy
    typename X_t::M_t M; // the "sum" of the spins, like the total magnetization
    v_t last_cluster_size; // the size of the last cluster
    std::vector<typename X_t::F_t> ReF;
    std::vector<typename X_t::F_t> ImF;

#ifdef BOND_DEPENDENCE
    std::function <double(v_t, const X_t&, v_t, const X_t&)> J; // coupling between sites
#else
    std::function <double(const X_t&, const X_t&)> J; // coupling between sites
#endif

#ifndef NOFIELD
#ifdef SITE_DEPENDENCE
    std::function <double(v_t, const X_t&)> H; // coupling with the external field
#else
    std::function <double(const X_t&)> H; // coupling with the external field
#endif
#endif

    state_t(D_t D, L_t L, double T,
#ifdef BOND_DEPENDENCE
        std::function <double(v_t, const X_t&, v_t, const X_t&)> J
#else
        std::function <double(const X_t&, const X_t&)> J
#endif
#ifndef NOFIELD
#ifdef SITE_DEPENDENCE
        , std::function <double(v_t, const X_t&)> H
#else
        , std::function <double(const X_t&)> H
#endif
#endif
           ) : D(D), L(L), g(D, L), T(T),
#ifndef NOFIELD
              R(),
#endif
              J(J)
#ifndef NOFIELD
               , H(H)
#endif
    {
      nv = g.nv;
      ne = g.ne;
      spins.resize(nv);
#ifdef BOND_DEPENDENCE
      E = 0;
      for (v_t v = 0; v < nv; v++) {
        for (const v_t &vn : g.v_adj[v]) {
          if (v < vn) {
            E -= J(v, spins[v], vn, spins[vn]);
          }
        }
      }
#else
      E = - (double)ne * J(spins[0], spins[0]);
#endif

#ifndef NOFIELD
      g.add_ext();
#ifdef SITE_DEPENDENCE
      for (v_t i = 0; i < nv; i++) {
        E -= H(i, spins[i]);
      }
#else
      E -= (double)nv * H(spins[0]);
#endif
#endif

      M = spins[0] * nv;
      last_cluster_size = 0;
      ReF.resize(D);
      ImF.resize(D);
      for (D_t i = 0; i < D; i++) {
        ReF[i] = spins[0] * 0.0;
        ImF[i] = spins[0] * 0.0;
      }
      precomputed_cos.resize(nv);
      precomputed_sin.resize(nv);
      for (v_t i = 0; i < nv; i++) {
        precomputed_cos[i].resize(D);
        precomputed_sin[i].resize(D);
        for (D_t j = 0; j < D; j++) {
          precomputed_cos[i][j] = cos(2 * M_PI * g.coordinate[i][j] / (double)L);
          precomputed_sin[i][j] = sin(2 * M_PI * g.coordinate[i][j] / (double)L);
        }
      }
    }

    void update_magnetization(const X_t& s_old, const X_t& s_new) {
      M += s_new - s_old;
    }

    void update_energy(const double& dE) {
      E += dE;
    }

    void update_fourierZero(v_t v, const X_t& s_old, const X_t& s_new) {
#ifdef DIMENSION
      for (D_t i = 0; i < DIMENSION; i++) {
#else
      for (D_t i = 0; i < D; i++) {
#endif
        ReF[i] += (s_new - s_old) * precomputed_cos[v][i];
        ImF[i] += (s_new - s_old) * precomputed_sin[v][i];
      }
    }
};