summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/cluster.h60
-rw-r--r--lib/orthogonal.h54
-rw-r--r--lib/state.h53
-rw-r--r--lib/wolff.h8
-rw-r--r--src/analyze_correlations.cpp6
-rw-r--r--src/wolff_heisenberg.cpp26
-rw-r--r--src/wolff_planar.cpp27
7 files changed, 164 insertions, 70 deletions
diff --git a/lib/cluster.h b/lib/cluster.h
index a20912e..ccd8725 100644
--- a/lib/cluster.h
+++ b/lib/cluster.h
@@ -13,6 +13,7 @@
#include <string.h>
#include <sys/types.h>
+#include "state.h"
#include "types.h"
#include "rand.h"
#include "stack.h"
@@ -50,52 +51,6 @@ T add(T, T);
template <class T>
T subtract(T, T);
-template <class T>
-T gen_rot(gsl_rng *r);
-
-template <class R_t, class X_t>
-class state_t {
- public:
- D_t D;
- L_t L;
- v_t nv;
- v_t ne;
- graph_t *g;
- double T;
- X_t *spins;
- R_t R;
- double E;
- X_t M; // the "sum" of the spins, like the total magnetization
-
- std::function <double(X_t, X_t)> J;
- std::function <double(X_t)> H;
-
- state_t(D_t D, L_t L, double T, std::function <double(X_t, X_t)> J, std::function <double(X_t)> H) : D(D), L(L), T(T), J(J), H(H) {
- graph_t *h = graph_create_square(D, L);
- nv = h->nv;
- ne = h->ne;
- g = graph_add_ext(h);
- graph_free(h);
- spins = (X_t *)malloc(nv * sizeof(X_t));
- for (v_t i = 0; i < nv; i++) {
- init (&(spins[i]));
- }
- init (&R);
- E = - (double)ne * J(spins[0], spins[0]) - (double)nv * H(spins[0]);
- M = scalar_multiple (nv, spins[0]);
- }
-
- ~state_t() {
- graph_free(g);
- for (v_t i = 0; i < nv; i++) {
- free_spin(spins[i]);
- }
- free(spins);
- free_spin(R);
- free_spin(M);
- }
-};
-
template <class R_t, class X_t>
v_t flip_cluster(state_t <R_t, X_t> *state, v_t v0, R_t r, gsl_rng *rand) {
v_t nv = 0;
@@ -103,7 +58,7 @@ v_t flip_cluster(state_t <R_t, X_t> *state, v_t v0, R_t r, gsl_rng *rand) {
ll_t *stack = NULL; // create a new stack
stack_push(&stack, v0); // push the initial vertex to the stack
- bool *marks = (bool *)calloc(state->g->nv, sizeof(bool));
+ bool *marks = (bool *)calloc(state->nv, sizeof(bool));
while (stack != NULL) {
v_t v = stack_pop(&stack);
@@ -112,14 +67,13 @@ v_t flip_cluster(state_t <R_t, X_t> *state, v_t v0, R_t r, gsl_rng *rand) {
X_t si_old, si_new;
R_t R_old, R_new;
- si_old = state->spins[v];
- R_old = state->R;
-
marks[v] = true;
- if (v == state->g->nv - 1) {
+ if (v == state->nv) {
+ R_old = state->R;
R_new = act (r, R_old);
} else {
+ si_old = state->spins[v];
si_new = act (r, si_old);
}
@@ -130,13 +84,13 @@ v_t flip_cluster(state_t <R_t, X_t> *state, v_t v0, R_t r, gsl_rng *rand) {
X_t sj;
- if (vn != state->g->nv - 1) {
+ if (vn != state->nv) {
sj = state->spins[vn];
}
double prob;
- bool is_ext = (v == state->g->nv - 1 || vn == state->g->nv - 1);
+ bool is_ext = (v == state->nv || vn == state->nv);
if (is_ext) {
X_t rs_old, rs_new;
diff --git a/lib/orthogonal.h b/lib/orthogonal.h
index 85f7a20..6166223 100644
--- a/lib/orthogonal.h
+++ b/lib/orthogonal.h
@@ -6,6 +6,7 @@
#include <gsl/gsl_randist.h>
#include <cmath>
+#include "state.h"
#include "types.h"
template <q_t q, class T>
@@ -143,21 +144,62 @@ orthogonal_t <q, T> act_inverse (orthogonal_t <q, T> m1, orthogonal_t <q, T> m2)
}
template <q_t q>
-void generate_rotation (gsl_rng *r, orthogonal_t <q, double> *ptr) {
- ptr->is_reflection = true;
- ptr->x = (double *)calloc(q, sizeof(double));
+orthogonal_t <q, double> generate_rotation_uniform (gsl_rng *r, const state_t <orthogonal_t <q, double>, vector_t <q, double>> *s) {
+ orthogonal_t <q, double> ptr;
+ ptr.is_reflection = true;
+ ptr.x = (double *)calloc(q, sizeof(double));
double v2 = 0;
for (q_t i = 0; i < q; i++) {
- ptr->x[i] = gsl_ran_ugaussian(r);
- v2 += ptr->x[i] * ptr->x[i];
+ ptr.x[i] = gsl_ran_ugaussian(r);
+ v2 += ptr.x[i] * ptr.x[i];
}
double mag_v = sqrt(v2);
for (q_t i = 0; i < q; i++) {
- ptr->x[i] /= mag_v;
+ ptr.x[i] /= mag_v;
}
+
+ return ptr;
+}
+
+template <q_t q>
+orthogonal_t <q, double> generate_rotation_perturbation (gsl_rng *r, const state_t <orthogonal_t <q, double>, vector_t <q, double>> *s, double epsilon) {
+ orthogonal_t <q, double> ptr;
+ vector_t <q, double> tmp_v;
+ ptr.is_reflection = true;
+
+ tmp_v.x = (double *)malloc(q * sizeof(double));
+
+ double tmp2 = 0;
+ double M2 = 0;
+ double tmpM = 0;
+
+ for (q_t i = 0; i < q; i++) {
+ tmp_v.x[i] = gsl_ran_ugaussian(r);
+ M2 += pow(s->M.x[i], 2);
+ tmpM += tmp_v.x[i] * s->M.x[i];
+ }
+
+ double v2 = 0;
+
+ for (q_t i = 0; i < q; i++) {
+ tmp_v.x[i] = (tmp_v.x[i] - tmpM * s->M.x[i] / M2) + epsilon * gsl_ran_ugaussian(r);
+ v2 += tmp_v.x[i] * tmp_v.x[i];
+ }
+
+ double mag_v = sqrt(v2);
+
+ for (q_t i = 0; i < q; i++) {
+ tmp_v.x[i] /= mag_v;
+ }
+
+ vector_t <q, double> v = act(s->R, tmp_v);
+ free(tmp_v.x);
+ ptr.x = v.x;
+
+ return ptr;
}
diff --git a/lib/state.h b/lib/state.h
new file mode 100644
index 0000000..8d4265b
--- /dev/null
+++ b/lib/state.h
@@ -0,0 +1,53 @@
+
+#pragma once
+
+#include <functional>
+
+#include "types.h"
+#include "graph.h"
+
+template <class R_t, class X_t>
+class state_t {
+ public:
+ D_t D;
+ L_t L;
+ v_t nv;
+ v_t ne;
+ graph_t *g;
+ double T;
+ X_t *spins;
+ R_t R;
+ double E;
+ X_t M; // the "sum" of the spins, like the total magnetization
+
+ std::function <double(X_t, X_t)> J;
+ std::function <double(X_t)> H;
+
+ state_t(D_t D, L_t L, double T, std::function <double(X_t, X_t)> J, std::function <double(X_t)> H) : D(D), L(L), T(T), J(J), H(H) {
+ graph_t *h = graph_create_square(D, L);
+ nv = h->nv;
+ ne = h->ne;
+ g = graph_add_ext(h);
+ graph_free(h);
+ spins = (X_t *)malloc(nv * sizeof(X_t));
+ for (v_t i = 0; i < nv; i++) {
+ init (&(spins[i]));
+ }
+ init (&R);
+ E = - (double)ne * J(spins[0], spins[0]) - (double)nv * H(spins[0]);
+ M = scalar_multiple (nv, spins[0]);
+ }
+
+ ~state_t() {
+ graph_free(g);
+ for (v_t i = 0; i < nv; i++) {
+ free_spin(spins[i]);
+ }
+ free(spins);
+ free_spin(R);
+ free_spin(M);
+ }
+};
+
+
+
diff --git a/lib/wolff.h b/lib/wolff.h
index caf413b..90470d5 100644
--- a/lib/wolff.h
+++ b/lib/wolff.h
@@ -2,7 +2,8 @@
#include <time.h>
#include <getopt.h>
-#include <cluster.h>
+#include "cluster.h"
+#include "state.h"
template <q_t q, class T>
double H_vector(vector_t <q, T> v1, T *H) {
@@ -12,7 +13,7 @@ double H_vector(vector_t <q, T> v1, T *H) {
}
template <class R_t, class X_t>
-void wolff(count_t N, D_t D, L_t L, double T, std::function <double(X_t, X_t)> J, std::function <double(X_t)> H, unsigned long timestamp, bool silent) {
+void wolff(count_t N, D_t D, L_t L, double T, std::function <double(X_t, X_t)> J, std::function <double(X_t)> H, std::function <R_t(gsl_rng *, const state_t <R_t, X_t> *)> gen_R, unsigned long timestamp, bool silent) {
state_t <R_t, X_t> s(D, L, T, J, H);
@@ -44,8 +45,7 @@ void wolff(count_t N, D_t D, L_t L, double T, std::function <double(X_t, X_t)> J
v_t v0 = gsl_rng_uniform_int(r, s.nv);
- R_t step;
- generate_rotation(r, &step);
+ R_t step = gen_R(r, &s);
cluster_size = flip_cluster <R_t, X_t> (&s, v0, step, r);
diff --git a/src/analyze_correlations.cpp b/src/analyze_correlations.cpp
index 6b8d28d..cf8e740 100644
--- a/src/analyze_correlations.cpp
+++ b/src/analyze_correlations.cpp
@@ -239,7 +239,11 @@ int main (int argc, char *argv[]) {
for (q_t i = 0; i < q - 1; i++) {
fscanf(metadata, "%lf, ", &(H[i]));
}
- fscanf(metadata, "%lf} |>\n", &(H[q - 1]));
+ char *field = (char *)malloc(32 * sizeof(char));
+ double epsilon;
+ fscanf(metadata, "%lf}, \"GENERATOR\" -> \"%[^\"]\", \"EPS\" -> %lf |>\n", &(H[q - 1]), field, &epsilon);
+
+ free(field);
free(H);
char *filename_E = (char *)malloc(128 * sizeof(char));
diff --git a/src/wolff_heisenberg.cpp b/src/wolff_heisenberg.cpp
index aed4156..83ea503 100644
--- a/src/wolff_heisenberg.cpp
+++ b/src/wolff_heisenberg.cpp
@@ -13,12 +13,14 @@ int main(int argc, char *argv[]) {
double *H = (double *)calloc(MAX_Q, sizeof(double));
bool silent = false;
+ bool use_pert = false;
int opt;
q_t J_ind = 0;
q_t H_ind = 0;
+ double epsilon = 1;
- while ((opt = getopt(argc, argv, "N:q:D:L:T:J:H:s")) != -1) {
+ while ((opt = getopt(argc, argv, "N:q:D:L:T:J:H:spe:")) != -1) {
switch (opt) {
case 'N': // number of steps
N = (count_t)atof(optarg);
@@ -39,6 +41,12 @@ int main(int argc, char *argv[]) {
case 's': // don't print anything during simulation. speeds up slightly
silent = true;
break;
+ case 'p':
+ use_pert = true;
+ break;
+ case 'e':
+ epsilon = atof(optarg);
+ break;
default:
exit(EXIT_FAILURE);
}
@@ -52,6 +60,18 @@ int main(int argc, char *argv[]) {
timestamp = spec.tv_sec*1000000000LL + spec.tv_nsec;
}
+ std::function <orthogonal_t <3, double>(gsl_rng *, const state_t <orthogonal_t <3, double>, vector_t <3, double>> *)> gen_R;
+
+ const char *pert_type;
+
+ if (use_pert) {
+ gen_R = std::bind(generate_rotation_perturbation <3>, std::placeholders::_1, std::placeholders::_2, epsilon);
+ pert_type = "PERTURB";
+ } else {
+ gen_R = generate_rotation_uniform <3>;
+ pert_type = "UNIFORM";
+ }
+
FILE *outfile_info = fopen("wolff_metadata.txt", "a");
fprintf(outfile_info, "<| \"ID\" -> %lu, \"MODEL\" -> \"HEISENBERG\", \"q\" -> 3, \"D\" -> %" PRID ", \"L\" -> %" PRIL ", \"NV\" -> %" PRIv ", \"NE\" -> %" PRIv ", \"T\" -> %.15f, \"H\" -> {", timestamp, D, L, L * L, D * L * L, T);
@@ -63,12 +83,12 @@ int main(int argc, char *argv[]) {
}
}
- fprintf(outfile_info, "} |>\n");
+ fprintf(outfile_info, "}, \"GENERATOR\" -> \"%s\", \"EPS\" -> %g |>\n", pert_type, epsilon);
fclose(outfile_info);
- wolff <orthogonal_t <3, double>, vector_t <3, double>> (N, D, L, T, dot <3, double>, std::bind(H_vector <3, double>, std::placeholders::_1, H), timestamp, silent);
+ wolff <orthogonal_t <3, double>, vector_t <3, double>> (N, D, L, T, dot <3, double>, std::bind(H_vector <3, double>, std::placeholders::_1, H), gen_R, timestamp, silent);
free(H);
diff --git a/src/wolff_planar.cpp b/src/wolff_planar.cpp
index 02ededc..2a3d02b 100644
--- a/src/wolff_planar.cpp
+++ b/src/wolff_planar.cpp
@@ -13,12 +13,14 @@ int main(int argc, char *argv[]) {
double *H = (double *)calloc(MAX_Q, sizeof(double));
bool silent = false;
+ bool use_pert = false;
int opt;
q_t J_ind = 0;
q_t H_ind = 0;
+ double epsilon = 1;
- while ((opt = getopt(argc, argv, "N:q:D:L:T:J:H:s")) != -1) {
+ while ((opt = getopt(argc, argv, "N:q:D:L:T:J:H:spe:")) != -1) {
switch (opt) {
case 'N': // number of steps
N = (count_t)atof(optarg);
@@ -39,6 +41,12 @@ int main(int argc, char *argv[]) {
case 's': // don't print anything during simulation. speeds up slightly
silent = true;
break;
+ case 'p':
+ use_pert = true;
+ break;
+ case 'e':
+ epsilon = atof(optarg);
+ break;
default:
exit(EXIT_FAILURE);
}
@@ -52,6 +60,19 @@ int main(int argc, char *argv[]) {
timestamp = spec.tv_sec*1000000000LL + spec.tv_nsec;
}
+ const char *pert_type;
+
+ std::function <orthogonal_t <2, double>(gsl_rng *, const state_t <orthogonal_t <2, double>, vector_t <2, double>> *)> gen_R;
+
+ if (use_pert) {
+ gen_R = std::bind(generate_rotation_perturbation <2>, std::placeholders::_1, std::placeholders::_2, epsilon);
+ pert_type = "PERTURB";
+ } else {
+ gen_R = generate_rotation_uniform <2>;
+ pert_type = "UNIFORM";
+ }
+
+
FILE *outfile_info = fopen("wolff_metadata.txt", "a");
fprintf(outfile_info, "<| \"ID\" -> %lu, \"MODEL\" -> \"PLANAR\", \"q\" -> 2, \"D\" -> %" PRID ", \"L\" -> %" PRIL ", \"NV\" -> %" PRIv ", \"NE\" -> %" PRIv ", \"T\" -> %.15f, \"H\" -> {", timestamp, D, L, L * L, D * L * L, T);
@@ -63,12 +84,12 @@ int main(int argc, char *argv[]) {
}
}
- fprintf(outfile_info, "} |>\n");
+ fprintf(outfile_info, "}, \"GENERATOR\" -> \"%s\", \"EPS\" -> %g |>\n", pert_type, epsilon);
fclose(outfile_info);
- wolff <orthogonal_t <2, double>, vector_t <2, double>> (N, D, L, T, dot <2, double>, std::bind(H_vector <2, double>, std::placeholders::_1, H), timestamp, silent);
+ wolff <orthogonal_t <2, double>, vector_t <2, double>> (N, D, L, T, dot <2, double>, std::bind(H_vector <2, double>, std::placeholders::_1, H), gen_R, timestamp, silent);
free(H);