{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fb551ef1",
   "metadata": {},
   "source": [
    "# Ising-Lenz Ergodicity: Analysis magnetisation autocorrelation\n",
    "\n",
    "    \n",
    "     (c) 2013, 2014, 2015, 2016, 2025 Süzen\n",
    "     GPL v3 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79dc2d1f",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "source": [
    "We computed average magnetisation autocorrelations across sizes and temperatures at $H=1.0$ and $J=0$\n",
    "\n",
    "Using autocorrelation curves, we identify autocorrelation times via differencing algorithm. The algorithm finds the lagged difference of the autocorrelation and report the relaxation time at a given epsilon threshold. `epsilon=1e-8, detect_lag=10`, also report bias corrected bootstrapped 95% confidence intervals. \n",
    "\n",
    "We plotted all autocorrelation and relaxation times under `plots/magnetisation` at all sizes and temperatures. Combined plots goes into `plots/magnetisationOverTemp`. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bb0960a",
   "metadata": {},
   "source": [
    "## Analysis methods and loads\n",
    "\n",
    "We provide analysis methods for easy of generation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8700f593",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "rm(list=ls()) \n",
    "require(\"isingLenzMC\"); # Developed and tested on v0.2.5 and R v4.5.1\n",
    "library(parallel)       # Core package\n",
    "\n",
    "source(\"../src/power_utilities.R\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91e324a8",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "autocorrelation_time_ci <- function(result, epsilon=1e-8, detect_lag=10) {\n",
    "    # Self time correaltion on result, return log(t), base e!\n",
    "    autocorr_times <- vector(\"numeric\", result$nrepeat)\n",
    "    for(i in 2:result$nrepeat) { # skip first trajectory\n",
    "        observe_mag <- result$average_magnetisation_repeats[[i]]\n",
    "        c_t <- self_time_correlation(observe_mag)\n",
    "        t <- result$mc_time\n",
    "        y <- log10(c_t)\n",
    "        x <- log10(t)\n",
    "        ix <- which(abs(diff(y, lag=detect_lag)) < epsilon)[1]\n",
    "        ixl <- as.numeric(t[ix])\n",
    "        autocorr_times[i] <- log10(ixl)\n",
    "    }\n",
    "    ix <- which(!is.na(autocorr_times))\n",
    "    get_mean_boot95_bca(autocorr_times[ix])\n",
    "}\n",
    "\n",
    "get_min_max_autocorr <- function(result) {\n",
    "    # Self time-correlation on result\n",
    "    # on log(c_t)\n",
    "    autocorr_times <- vector(\"numeric\", result$nrepeat)\n",
    "    observe_mag <- result$average_magnetisation_repeats[[2]]\n",
    "    c_t <- self_time_correlation(observe_mag)\n",
    "    y <- log(c_t)\n",
    "    minct <- min(y)\n",
    "    maxct <- max(y)\n",
    "    for(i in 3:result$nrepeat) {\n",
    "        observe_mag <- result$average_magnetisation_repeats[[i]]\n",
    "        c_t <- self_time_correlation(observe_mag)\n",
    "        y <- log(c_t)\n",
    "        minct_ <- min(y)\n",
    "        maxct_ <- max(y)\n",
    "        if(minct_ <= minct) minct <- minct_\n",
    "        if(maxct_ >= maxct) maxct <- maxct_\n",
    "    }\n",
    "    c(minct, maxct)\n",
    "}\n",
    "\n",
    "info_autocorrelation_time <- function(result) {\n",
    "  # Get Autocorrelation time simpy testing for epsilon on difference.\n",
    "  # Compute CI via bCA\n",
    "    ac_time <- autocorrelation_time_ci(result)\n",
    "    if(result$transP == 1) dynamics <- \"Metropolis\"\n",
    "    if(result$transP == 2) dynamics <- \"Glauber\"\n",
    "    as.data.frame(list(\"N\"=result$N, \"beta\"=result$ikBT, \"J\"=result$J, \"H\"=result$H, \n",
    "        \"dynamics\"=dynamics, \"transP\"=result$transP,\n",
    "        \"ac_time_mean\"=ac_time$mean, \"ac_time_upper\"=ac_time$upper, \n",
    "        \"ac_time_lower\"=ac_time$lower))\n",
    "}\n",
    "\n",
    "plot_ac_time <- function(result, base_plot=\"../plots/magnetisation/\") {\n",
    "  # Plot autocorrelation times\n",
    "  if(result$transP == 1) dynamics <- \"Metropolis\"\n",
    "  if(result$transP == 2) dynamics <- \"Glauber\"\n",
    "  fname <- paste(base_plot, dynamics, \"N\", result$N, \"beta\", result$ikBT, \".pdf\", sep = \"\")\n",
    "  pdf(fname, pointsize = 18) # pointsize will effect all label and title font sizes.\n",
    "  minmaxmag <- get_min_max_autocorr(result)\n",
    "  bci <- autocorrelation_time_ci(result)\n",
    "  for (i in 2:result$nrepeat) {\n",
    "    observe_mag <- result$average_magnetisation_repeats[[i]]\n",
    "    c_t <- self_time_correlation(observe_mag)\n",
    "    t <- result$mc_time\n",
    "    y <- log10(c_t)\n",
    "    x <- log10(t)\n",
    "    if (i == 2) {\n",
    "      plot(x, y, lty = 1, lwd = 0.02, type = \"l\", ylim = minmaxmag, ann=FALSE,\n",
    "          cex.lab = 1.2,  cex.axis = 1.2, cex.main = 1, cex.sub = 1)\n",
    "    }\n",
    "    if (i > 2) {\n",
    "      lines(x, y, lty = 1, lwd = 0.02, type = \"l\", ylim = minmaxmag)\n",
    "    }\n",
    "  }\n",
    "  abline(v = bci$mean, lty=2, lwd = 3)\n",
    "  abline(v = bci$upper, lty=3, lwd = 3)\n",
    "  abline(v = bci$lower, lty=3, lwd = 3)\n",
    "  xlabel <- \"Log Scale MC Time Steps\"\n",
    "  ylabel <- \"Log Scale Autocorrelation\"\n",
    "  title_main <- bquote(paste(\"Average Magnetisation Autocorrelation\"))\n",
    "  N    <- result$N\n",
    "  ikBT <- result$ikBT\n",
    "  subtitle <- bquote(paste(\n",
    "    .(dynamics), \" N=\", .(N), \" \", beta, \"=\", .(ikBT)\n",
    "  ))\n",
    "  title(title_main, xlab=xlabel, ylab=ylabel)\n",
    "  mtext(subtitle)\n",
    "    legend(\"bottomright\",\n",
    "      legend = c(\"Time Correlation Curves\", \"Autorcorrelation Time (Mean)\", \"Autorcorrelation Time (CI)\"),\n",
    "      lty = c(1, 2, 3),\n",
    "      lwd = 3,\n",
    "      bty = \"n\",\n",
    "    )\n",
    "  dev.off()\n",
    "\n",
    "}\n",
    "\n",
    "get_ac_times_df <- function(average_magnetisation_data, iplot=TRUE, base_plot = \"../plots/magnetisation/\") {\n",
    "  # Compute autocorrelation and return info data.frame\n",
    "  # Plot if asked.\n",
    "    result <- average_magnetisation_data[[1]]\n",
    "    df_ac_time <- info_autocorrelation_time(result)\n",
    "    for(i in 2:length(average_magnetisation_data)) {\n",
    "        result <- average_magnetisation_data[[i]]\n",
    "        df_ac_time <- rbind.data.frame(df_ac_time, info_autocorrelation_time(result))\n",
    "        if(iplot) plot_ac_time(result, base_plot)\n",
    "    }\n",
    "    df_ac_time\n",
    "}\n",
    "\n",
    "get_magnetisation_ac_over_temp <- function(df_ac_time, N, transP) {\n",
    "    df <- df_ac[df_ac['N'] == N & df_ac['transP'] == transP,] [,c('beta', 'ac_time_mean','ac_time_lower', 'ac_time_upper')]\n",
    "    x <- df['beta'][,1]\n",
    "    y <- df['ac_time_mean'][,1]\n",
    "    y_lower <- df['ac_time_lower'][,1]\n",
    "    y_upper <- df['ac_time_upper'][,1]\n",
    "    list(\"x\"=x, \"y\"=y, \"y_lower\"=y_lower,\"y_upper\"=y_upper)\n",
    "}\n",
    "\n",
    "magnetisation_ac_over_temp <- function(df_ac_time, N, transP, pcount=1, base_plot=\"../plots/magnetisationOverTemp/\") {\n",
    "    if(transP == 1) dynamics <- \"Metropolis\"\n",
    "    if(transP == 2) dynamics <- \"Glauber\"\n",
    "    fname <- paste(base_plot, dynamics, N, \".pdf\", sep = \"\")\n",
    "    pdf(fname, pointsize = 18) # pointsize will effect all label and title font sizes.\n",
    "    val <- get_magnetisation_ac_over_temp(df_ac_time, N, transP)\n",
    "    plot(val$x, val$y, lty=1, type=\"p\", pch=pcount, ann=FALSE, ylim=c(3.0, 6.1))\n",
    "    arrows(val$x, val$y_lower, val$x, val$y_upper, length=0.05, angle=90, code=3)\n",
    "    xlabel <- \"Temperature Range\"\n",
    "    ylabel <- \"Log Scale Autocorrelation MC Time\"\n",
    "    title_main <- bquote(paste(\"Autocorrelation Times\"))\n",
    "    subtitle <- bquote(paste(\n",
    "        \"Average Magnetisation: \", .(dynamics), \" N=\", .(N)\n",
    "    ))\n",
    "    title(title_main, xlab=xlabel, ylab=ylabel)\n",
    "    mtext(subtitle)\n",
    "    dev.off()\n",
    "    list(\"x\"=val$x, \"y\"=val$y, \"y_lower\"=val$y_lower,\"y_upper\"=val$y_upper)\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c31095ad",
   "metadata": {},
   "source": [
    "## Computation\n",
    "\n",
    "We compute and pooled the autocorrelation times for each case using the generated dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f6eecca6",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Load dataset\n",
    "# Compute autocorrelation times\n",
    "average_magnetisation_data <- readRDS(\"../datasets/ising1Dmagnetisation.rds\")\n",
    "df_ac <- get_ac_times_df(average_magnetisation_data, iplot = TRUE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b930e22",
   "metadata": {},
   "source": [
    "## Plots\n",
    "\n",
    "Mentioned plots as in introduction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd07225a",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "N <- 512\n",
    "transP <- 1\n",
    "val512_1 <- magnetisation_ac_over_temp(df_ac_time, N, transP)\n",
    "transP <- 2\n",
    "val512_2 <- magnetisation_ac_over_temp(df_ac_time, N, transP, pcount = 2)\n",
    "N <- 1024\n",
    "transP <- 1\n",
    "val1024_1 <- magnetisation_ac_over_temp(df_ac_time, N, transP, pcount = 3)\n",
    "transP <- 2\n",
    "val1024_2 <- magnetisation_ac_over_temp(df_ac_time, N, transP, pcount = 4)\n",
    "N <- 1536\n",
    "transP <- 1\n",
    "val1536_1 <- magnetisation_ac_over_temp(df_ac_time, N, transP, pcount=5)\n",
    "transP <- 2\n",
    "val1536_2 <- magnetisation_ac_over_temp(df_ac_time, N, transP, pcount=6)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8102d8d8",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Metropolis\n",
    "base_plot <- \"../plots/magnetisationOverTemp/\"\n",
    "fname <- paste(base_plot, \"ac_times_metropolis.pdf\", sep = \"\")\n",
    "pdf(fname, pointsize = 18) # pointsize will effect all label and title font sizes.\n",
    "val <- val512_1\n",
    "plot(val$x, val$y, lty=1, pch=1, type=\"p\", col=\"black\", ann=FALSE, ylim=c(3.0, 6.1), xlim=c(0.45, 1.55))\n",
    "arrows(val$x, val$y_lower, val$x, val$y_upper, col=\"black\",length=0.05, angle=90, code=3)\n",
    "val <- val1024_1\n",
    "lines(val$x, val$y, lty=2, pch=2, type=\"p\", col=\"blue\",ann=FALSE, ylim=c(3.0, 6.1), xlim=c(0.45, 1.55))\n",
    "arrows(val$x, val$y_lower, val$x, val$y_upper, col=\"blue\", length=0.05, angle=90, code=3)\n",
    "val <- val1536_1\n",
    "lines(val$x, val$y, lty=3, pch=3, type=\"p\", col=\"red\", ann=FALSE, ylim=c(3.0, 6.1), xlim=c(0.45, 1.55))\n",
    "arrows(val$x, val$y_lower, val$x, val$y_upper, col=\"red\", length=0.05, angle=90, code=3)\n",
    "xlabel <- \"Temperature Range\"\n",
    "ylabel <- \"Log Scale Autocorrelation MC Time\"\n",
    "title_main <- bquote(paste(\"Autocorrelation Times\"))\n",
    "subtitle <- bquote(paste(\n",
    "    \"Average Magnetisation: Metropolis\"\n",
    "))\n",
    "title(title_main, xlab=xlabel, ylab=ylabel)\n",
    "mtext(subtitle)\n",
    "  legend(\"bottomleft\",\n",
    "    legend = c(\"N=512\", \"N=1024\", \"N=1536\"),\n",
    "    pch = c(1, 2, 3),\n",
    "    col = c(\"black\", \"blue\", \"red\"),\n",
    "    lwd = 2,\n",
    "    bty = \"n\",\n",
    "  )\n",
    "dev.off()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8412b79",
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "# Glauber\n",
    "base_plot <- \"../plots/magnetisationOverTemp/\"\n",
    "fname <- paste(base_plot, \"ac_times_glauber.pdf\", sep = \"\")\n",
    "pdf(fname, pointsize = 18) # pointsize will effect all label and title font sizes.\n",
    "val <- val512_2\n",
    "plot(val$x, val$y, lty=1, pch=1, type=\"p\", col=\"black\", ann=FALSE, ylim=c(3.0, 6.1), xlim=c(0.45, 1.55))\n",
    "arrows(val$x, val$y_lower, val$x, val$y_upper, col=\"black\",length=0.05, angle=90, code=3)\n",
    "val <- val1024_2\n",
    "lines(val$x, val$y, lty=2, pch=2, type=\"p\", col=\"blue\",ann=FALSE, ylim=c(3.0, 6.1), xlim=c(0.45, 1.55))\n",
    "arrows(val$x, val$y_lower, val$x, val$y_upper, col=\"blue\", length=0.05, angle=90, code=3)\n",
    "val <- val1536_2\n",
    "lines(val$x, val$y, lty=3, pch=3, type=\"p\", col=\"red\", ann=FALSE, ylim=c(3.0, 6.1), xlim=c(0.45, 1.55))\n",
    "arrows(val$x, val$y_lower, val$x, val$y_upper, col=\"red\", length=0.05, angle=90, code=3)\n",
    "xlabel <- \"Temperature Range\"\n",
    "ylabel <- \"Log Scale Autocorrelation MC Time\"\n",
    "title_main <- bquote(paste(\"Autocorrelation Times\"))\n",
    "subtitle <- bquote(paste(\n",
    "    \"Average Magnetisation: Glauber\"\n",
    "))\n",
    "title(title_main, xlab=xlabel, ylab=ylabel)\n",
    "mtext(subtitle)\n",
    "  legend(\"bottomleft\",\n",
    "    legend = c(\"N=512\", \"N=1024\", \"N=1536\"),\n",
    "    pch = c(1, 2, 3),\n",
    "    col = c(\"black\", \"blue\", \"red\"),\n",
    "    lwd = 2,\n",
    "    bty = \"n\",\n",
    "  )\n",
    "dev.off()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "codemirror_mode": "r",
   "file_extension": ".r",
   "mimetype": "text/x-r-source",
   "name": "R",
   "pygments_lexer": "r",
   "version": "4.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
