From 30534606d5690e176d168f640f55162fa15f0a19 Mon Sep 17 00:00:00 2001
From: Jaron Kent-Dobias <jaron@kent-dobias.com>
Date: Thu, 2 Nov 2017 11:02:07 -0400
Subject: major changes (again) to the measurement of autocorrelation

---
 lib/queue.c       | 19 +++++++++++++++++++
 lib/queue.h       |  7 +++++++
 lib/wolff.h       |  2 +-
 lib/wolff_tools.c | 30 ++++++++++++++++++++----------
 src/wolff.c       | 19 +++++++++++++------
 5 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/lib/queue.c b/lib/queue.c
index aebbb2a..0823518 100644
--- a/lib/queue.c
+++ b/lib/queue.c
@@ -9,6 +9,14 @@ void stack_push(ll_t **q, uint32_t x) {
   *q = nq;
 }
 
+void stack_push_d(dll_t **q, double x) {
+  dll_t *nq = malloc(sizeof(dll_t));
+  nq->x = x;
+  nq->next = *q;
+
+  *q = nq;
+}
+
 uint32_t stack_pop(ll_t **q) {
   ll_t *old_q = *q;
 
@@ -20,6 +28,17 @@ uint32_t stack_pop(ll_t **q) {
   return x;
 }
 
+double stack_pop_d(dll_t **q) {
+  dll_t *old_q = *q;
+
+  *q = old_q->next;
+  double x = old_q->x;
+
+  free(old_q);
+
+  return x;
+}
+
 bool stack_contains(const ll_t *q, uint32_t x) {
   if (q == NULL) {
     return false;
diff --git a/lib/queue.h b/lib/queue.h
index c7acec1..23834ba 100644
--- a/lib/queue.h
+++ b/lib/queue.h
@@ -11,8 +11,15 @@ typedef struct ll_tag {
   struct ll_tag *next;
 } ll_t;
 
+typedef struct dll_tag {
+  double x;
+  struct dll_tag *next;
+} dll_t;
+
 void stack_push(ll_t **q, uint32_t x);
+void stack_push_d(dll_t **q, double x);
 
 uint32_t stack_pop(ll_t **q);
+double stack_pop_d(dll_t **q);
 
 bool stack_contains(const ll_t *q, uint32_t x);
diff --git a/lib/wolff.h b/lib/wolff.h
index cf24427..66ce493 100644
--- a/lib/wolff.h
+++ b/lib/wolff.h
@@ -54,7 +54,7 @@ typedef struct {
   uint64_t n;
   uint64_t W;
   double *OO;
-  double *Op;
+  dll_t *Op;
   double O;
   double O2;
 } autocorr_t;
diff --git a/lib/wolff_tools.c b/lib/wolff_tools.c
index 92e8302..a417d4e 100644
--- a/lib/wolff_tools.c
+++ b/lib/wolff_tools.c
@@ -258,21 +258,31 @@ void update_autocorr(autocorr_t *OO, double O) {
   OO->O = add_to_avg(OO->O, O, OO->n);
   OO->O2 = add_to_avg(OO->O2, pow(O, 2), OO->n);
 
-  uint64_t lim = OO->W;
-
-  if (OO->n < OO->W) {
-    lim = OO->n;
+  dll_t *Otmp = OO->Op;
+  dll_t *Osave;
+  uint64_t t = 0;
+
+  while (Otmp != NULL) {
+    OO->OO[t] = add_to_avg(OO->OO[t], O * (Otmp->x), OO->n - t - 1);
+    t++;
+    if (t == OO->W - 1) {
+      Osave = Otmp;
+    }
+    Otmp = Otmp->next;
   }
 
-  for (uint64_t t = 0; t < lim; t++) {
-    OO->OO[t] = add_to_avg(OO->OO[t], O * OO->Op[t], OO->n - t - 1);
+  if (t == OO->W) {
+    if (OO->W == 1) {
+      free(OO->Op);
+      OO->Op = NULL;
+    } else {
+      free(Osave->next);
+      Osave->next = NULL;
+    }
   }
 
-  for (uint64_t t = 0; t < OO->W - 1; t++) {
-    OO->Op[OO->W - 1 - t] = OO->Op[OO->W - 2 - t];
-  }
+  stack_push_d(&(OO->Op), O);
 
-  OO->Op[0] = O;
   OO->n++;
 }
 
diff --git a/src/wolff.c b/src/wolff.c
index 40a88e6..1e62c8c 100644
--- a/src/wolff.c
+++ b/src/wolff.c
@@ -8,13 +8,14 @@ int main(int argc, char *argv[]) {
   lattice_t lat;
   uint16_t L;
   uint32_t min_runs, lattice_i, sim_i;
-  uint64_t N, n, W;
+  uint64_t N, n, W, ac_skip;
   double T, H, eps;
 
   sim = WOLFF;
   L = 128;
   N = 100000000000000;
   W = 10;
+  ac_skip = 1;
   n = 3;
   lat = SQUARE_LATTICE;
   use_dual = false;
@@ -26,7 +27,7 @@ int main(int argc, char *argv[]) {
   output_state = false;
   min_runs = 10;
 
-  while ((opt = getopt(argc, argv, "n:N:L:T:H:m:e:oq:DMas:W:")) != -1) {
+  while ((opt = getopt(argc, argv, "n:N:L:T:H:m:S:e:oq:DMas:W:")) != -1) {
     switch (opt) {
     case 'N':
       N = (uint64_t)atof(optarg);
@@ -34,6 +35,9 @@ int main(int argc, char *argv[]) {
     case 'W':
       W = (uint64_t)atof(optarg);
       break;
+    case 'S':
+      ac_skip = (uint64_t)atof(optarg);
+      break;
     case 'n':
       n = (uint64_t)atof(optarg);
       break;
@@ -148,7 +152,6 @@ int main(int argc, char *argv[]) {
     autocorr = (autocorr_t *)calloc(1, sizeof(autocorr_t));
     autocorr->W = W;
     autocorr->OO = (double *)calloc(W, sizeof(double));
-    autocorr->Op = (double *)calloc(W, sizeof(double));
   }
 
   printf("\n");
@@ -167,7 +170,9 @@ int main(int argc, char *argv[]) {
       n_steps++;
 
       if (record_autocorrelation && n_runs > 0) {
-        update_autocorr(autocorr, s->H);
+        if (n_steps % ac_skip == 0) {
+          update_autocorr(autocorr, s->H);
+        }
         update_meas(clust, tmp_flips);
       }
     }
@@ -228,10 +233,12 @@ int main(int argc, char *argv[]) {
     double dttau = sqrt(4.0 / autocorr->n * (pow(ttau, 2) * (W +(1+kappa)/(1-kappa)-0.5) + kappa * X / pow(1-kappa, 2) + pow(kappa, 2) * Y / pow(1-kappa, 4)));
     
     free(autocorr->OO);
-    free(autocorr->Op);
+    while (autocorr->Op != NULL) {
+      stack_pop_d(&(autocorr->Op));
+    }
     free(autocorr);
     
-    tau = ttau * clust->x / h->nv;
+    tau = ttau * ac_skip * clust->x / h->nv;
     dtau = tau * sqrt(pow(dttau / ttau, 2) + pow(clust->dx / clust->x, 2));
   }
 
-- 
cgit v1.2.3-70-g09d2