diff options
46 files changed, 759 insertions, 2921 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a435b29..73922c6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,10 +1,11 @@ -add_library(wolff_examples INTERFACE) +add_executable(ising ising.cpp) +add_executable(animate_ising animate_ising.cpp) +add_executable(xy On.cpp) -target_include_directories(wolff_examples INTERFACE include) +add_compile_definitions(xy WOLFF_N=2) -add_executable(simple_ising simple_ising.cpp) -target_link_libraries(simple_ising wolff) - -add_subdirectory(src) +target_link_libraries(ising wolff) +target_link_libraries(animate_ising wolff GL GLU glut) +target_link_libraries(xy wolff) diff --git a/examples/On.cpp b/examples/On.cpp new file mode 100644 index 0000000..e045f52 --- /dev/null +++ b/examples/On.cpp @@ -0,0 +1,82 @@ + +#include <getopt.h> +#include <iostream> +#include <chrono> + +#include "simple_measurement.hpp" + +#include <wolff/models/vector.hpp> +#include <wolff/models/orthogonal.hpp> +#include <wolff.hpp> + +int main(int argc, char *argv[]) { + + // set defaults + N_t N = (N_t)1e4; + D_t D = 2; + L_t L = 128; + double T = 0.8; + vector_t<WOLFF_N, double> H; + H.fill(0.0); + q_t Hi = 0; + + int opt; + + // take command line arguments + while ((opt = getopt(argc, argv, "N:D:L:T:H:")) != -1) { + switch (opt) { + case 'N': // number of steps + N = (N_t)atof(optarg); + break; + case 'D': // dimension + D = atoi(optarg); + break; + case 'L': // linear size + L = atoi(optarg); + break; + case 'T': // temperature + T = atof(optarg); + break; + case 'H': // external field + H[Hi] = atof(optarg); + Hi++; + break; + default: + exit(EXIT_FAILURE); + } + } + + // define the spin-spin coupling + std::function <double(const vector_t<WOLFF_N, double>&, const vector_t<WOLFF_N, double>&)> Z = [] (const vector_t<WOLFF_N, double>& s1, const vector_t<WOLFF_N, double>& s2) -> double { + return s1 * s2; + }; + + // define the spin-field coupling + std::function <double(const vector_t<WOLFF_N, double>&)> B = [&] (const vector_t<WOLFF_N, double>& s) -> double { + return H * s; + }; + + // initialize the system + wolff_system<orthogonal_t<WOLFF_N, double>, vector_t<WOLFF_N, double>> S(D, L, T, Z, B); + + std::function <orthogonal_t<WOLFF_N, double>(std::mt19937&, const vector_t<WOLFF_N, double>&)> gen_R = generate_rotation_uniform<WOLFF_N>; + + // initailze the measurement object + simple_measurement A(S); + + // initialize the random number generator + auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + std::mt19937 rng{seed}; + + // run wolff N times + wolff<orthogonal_t<WOLFF_N, double>, vector_t<WOLFF_N, double>>(N, S, gen_R, A, rng); + + // print the result of our measurements + std::cout << "Wolff complete!\nThe average energy per site was " << A.avgE() / S.nv + << ".\nThe average magnetization per site was " << A.avgM() / S.nv + << ".\nThe average cluster size per site was " << A.avgC() / S.nv << ".\n"; + + // exit + return 0; +} + diff --git a/examples/animate_ising.cpp b/examples/animate_ising.cpp new file mode 100644 index 0000000..e33736e --- /dev/null +++ b/examples/animate_ising.cpp @@ -0,0 +1,133 @@ + +#include <getopt.h> +#include <iostream> +#include <chrono> + +#include <GL/glut.h> + +#include <wolff/models/ising.hpp> +#include <wolff/finite_states.hpp> +#include <wolff.hpp> + +class draw_ising : public wolff_measurement<ising_t, ising_t> { + private: + unsigned int frame_skip; + v_t C; + public: + draw_ising(const wolff_system<ising_t, ising_t>& S, unsigned int window_size, unsigned int frame_skip, int argc, char *argv[]) : frame_skip(frame_skip){ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); + glutInitWindowSize(window_size, window_size); + glutCreateWindow("wolff"); + glClearColor(0.0,0.0,0.0,0.0); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0.0, S.L, 0.0, S.L); + } + + void pre_cluster(N_t, N_t, const wolff_system<ising_t, ising_t>& S, v_t, const ising_t&) { + glClear(GL_COLOR_BUFFER_BIT); + for (v_t i = 0; i < pow(S.L, 2); i++) { + if (S.s[i].x == S.s0.x) { + glColor3f(0.0, 0.0, 0.0); + } else { + glColor3f(1.0, 1.0, 1.0); + } + glRecti(i / S.L, i % S.L, (i / S.L) + 1, (i % S.L) + 1); + } + glFlush(); + C = 0; + } + + void plain_bond_visited(const wolff_system<ising_t, ising_t>&, v_t, const ising_t&, v_t, double dE) {} + + void ghost_bond_visited(const wolff_system<ising_t, ising_t>&, v_t, const ising_t& s_old, const ising_t& s_new, double dE) {} + + void plain_site_transformed(const wolff_system<ising_t, ising_t>& S, v_t i, const ising_t&) { + glColor3f(1.0, 0.0, 0.0); + glRecti(i / S.L, i % S.L, (i / S.L) + 1, (i % S.L) + 1); + C++; + if (C % frame_skip == 0) { + glFlush(); + } + } + + void ghost_site_transformed(const wolff_system<ising_t, ising_t>&, const ising_t&) {} + + void post_cluster(N_t, N_t, const wolff_system<ising_t, ising_t>&) {} +}; + +int main(int argc, char *argv[]) { + + // set defaults + N_t N = (N_t)1e4; + D_t D = 2; + L_t L = 128; + double T = 2.26918531421; + double H = 0.0; + unsigned int window_size = 512; + unsigned int frame_skip = 1; + + int opt; + + // take command line arguments + while ((opt = getopt(argc, argv, "N:D:L:T:H:w:f:")) != -1) { + switch (opt) { + case 'N': // number of steps + N = (N_t)atof(optarg); + break; + case 'D': // dimension + D = atoi(optarg); + break; + case 'L': // linear size + L = atoi(optarg); + break; + case 'T': // temperature + T = atof(optarg); + break; + case 'H': // external field + H = atof(optarg); + break; + case 'w': + window_size = atoi(optarg); + break; + case 'f': + frame_skip = atoi(optarg); + break; + default: + exit(EXIT_FAILURE); + } + } + + // define the spin-spin coupling + std::function <double(const ising_t&, const ising_t&)> Z = [] (const ising_t& s1, const ising_t& s2) -> double { + return (double)(s1 * s2); + }; + + // define the spin-field coupling + std::function <double(const ising_t&)> B = [=] (const ising_t& s) -> double { + return H * s; + }; + + // initialize the system + wolff_system<ising_t, ising_t> S(D, L, T, Z, B); + + // define function that generates self-inverse rotations + std::function <ising_t(std::mt19937&, const ising_t&)> gen_R = [] (std::mt19937&, const ising_t& s) -> ising_t { + return ising_t(true); + }; + + // initailze the measurement object + draw_ising A(S, window_size, frame_skip, argc, argv); + + // initialize the random number generator + auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + std::mt19937 rng{seed}; + + // run wolff N times + wolff<ising_t, ising_t>(N, S, gen_R, A, rng); + + // exit + return 0; +} + diff --git a/examples/include/colors.h b/examples/include/colors.h deleted file mode 100644 index abf137c..0000000 --- a/examples/include/colors.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include <wolff/types.h> - -double hue_to_R(double theta) { - if (((M_PI / 3 <= theta) && (theta < 2 * M_PI / 3)) || ((4 * M_PI / 3 <= theta) && (theta < 5 * M_PI / 3))) { - return 1.0 - fabs(fmod(theta / (2 * M_PI / 6), 2) - 1.0); - } else if (((0 <= theta) && (theta < M_PI / 3)) || ((5 * M_PI / 3 <= theta) && (theta <= 2 * M_PI))) { - return 1.0; - } else { - return 0.0; - } -} - -double hue_to_G(double theta) { - if (((0 <= theta) && (theta < M_PI / 3)) || ((M_PI <= theta) && (theta < 4 * M_PI / 3))) { - return 1.0 - fabs(fmod(theta / (2 * M_PI / 6), 2) - 1.0); - } else if (((M_PI / 3 <= theta) && (theta < 2 * M_PI / 3)) || ((2 * M_PI / 3 <= theta) && (theta < M_PI))) { - return 1.0; - } else { - return 0.0; - } -} - -double hue_to_B(double theta) { - if (((2 * M_PI / 3 <= theta) && (theta < M_PI)) || ((5 * M_PI / 3 <= theta) && (theta <= 2 * M_PI))) { - return 1.0 - fabs(fmod(theta / (2 * M_PI / 6), 2) - 1.0); - } else if (((M_PI <= theta) && (theta < 4 * M_PI / 3)) || ((4 * M_PI / 3 <= theta) && (theta < 5 * M_PI / 3))) { - return 1.0; - } else { - return 0.0; - } -} - diff --git a/examples/include/correlation.hpp b/examples/include/correlation.hpp deleted file mode 100644 index da8ab7f..0000000 --- a/examples/include/correlation.hpp +++ /dev/null @@ -1,23 +0,0 @@ - -#pragma once - -#include <wolff/types.h> -#include <wolff/state.hpp> - -#include <fftw3.h> - -template <class X_t> -double correlation_length(const std::vector<typename X_t::F_t>& ReF, const std::vector<typename X_t::F_t>& ImF, D_t D) { - double total = 0; - -#ifdef DIMENSION - for (D_t j = 0; j < DIMENSION; j++) { -#else - for (D_t j = 0; j < D; j++) { -#endif - total += norm_squared(ReF[j]) + norm_squared(ImF[j]); - } - - return total / D; -} - diff --git a/examples/include/measure.hpp b/examples/include/measure.hpp deleted file mode 100644 index bf8baab..0000000 --- a/examples/include/measure.hpp +++ /dev/null @@ -1,159 +0,0 @@ - -#pragma once - -#include <wolff/state.hpp> -#include <wolff/meas.h> -#include "correlation.hpp" -#include <functional> - -#define POSSIBLE_MEASUREMENTS 4 -const unsigned char measurement_energy = 1 << 0; -const unsigned char measurement_clusterSize = 1 << 1; -const unsigned char measurement_magnetization = 1 << 2; -const unsigned char measurement_fourierZero = 1 << 3; - -char const *measurement_labels[] = {"E", "S", "M", "F"}; - -template <class R_t, class X_t> -class wolff_research_measurements : public wolff_measurement<R_t, X_t> { - private: - std::vector<std::vector<double>> precomputed_sin; - std::vector<std::vector<double>> precomputed_cos; - FILE **files; - D_t D; - unsigned char flags; - std::function <void(const state_t <R_t, X_t>&, const wolff_research_measurements<R_t, X_t>&)> other_f; - bool silent; - public: - v_t last_cluster_size; - double E; - typename X_t::M_t M; - std::vector<typename X_t::F_t> ReF; - std::vector<typename X_t::F_t> ImF; - - wolff_research_measurements(unsigned char flags, unsigned long timestamp, std::function <void(const state_t <R_t, X_t>&, const wolff_research_measurements<R_t, X_t>&)> other_f, state_t<R_t, X_t>& s, bool silent) : flags(flags), D(s.D), other_f(other_f), silent(silent) { - FILE **files = (FILE **)calloc(POSSIBLE_MEASUREMENTS, sizeof(FILE *)); - - for (uint8_t i = 0; i < POSSIBLE_MEASUREMENTS; i++) { - if (flags & (1 << i)) { - char *filename = (char *)malloc(255 * sizeof(char)); - sprintf(filename, "wolff_%lu_%s.dat", timestamp, measurement_labels[i]); - files[i] = fopen(filename, "wb"); - free(filename); - } - } - -#ifdef BOND_DEPENDENCE - E = 0; - for (v_t v = 0; v < s.nv; v++) { - for (const v_t &vn : s.g.v_adj[v]) { - if (v < vn) { - E -= s.J(v, s.spins[v], vn, s.spins[vn]); - } - } - } -#else - E = - (double)s.ne * s.J(s.spins[0], s.spins[0]); -#endif - -#ifndef NOFIELD -#ifdef SITE_DEPENDENCE - for (v_t i = 0; i < s.nv; i++) { - E -= s.H(i, s.spins[i]); - } -#else - E -= (double)s.nv * s.H(s.spins[0]); -#endif -#endif - - M = s.spins[0] * s.nv; - - ReF.resize(s.D); - ImF.resize(s.D); - for (D_t i = 0; i < s.D; i++) { - ReF[i] = s.spins[0] * 0.0; - ImF[i] = s.spins[0] * 0.0; - } - precomputed_cos.resize(s.nv); - precomputed_sin.resize(s.nv); - for (v_t i = 0; i < s.nv; i++) { - precomputed_cos[i].resize(s.D); - precomputed_sin[i].resize(s.D); - for (D_t j = 0; j < s.D; j++) { - precomputed_cos[i][j] = cos(2 * M_PI * s.g.coordinate[i][j] / (double)s.L); - precomputed_sin[i][j] = sin(2 * M_PI * s.g.coordinate[i][j] / (double)s.L); - } - } - - if (!silent) printf("\n"); - - } - - void pre_cluster(const state_t<R_t, X_t>& s, count_t step, count_t N, v_t v0, const R_t& R) { - last_cluster_size = 0; - if (!silent) printf("\033[F\033[JWOLFF: step %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n", step, N, E, last_cluster_size); - - } - - void plain_bond_added(v_t vi, const X_t& si_old, const X_t& si_new, v_t vn, const X_t& sn, double dE) { - E += dE; - } - - void ghost_bond_added(v_t v, const X_t& rs_old, const X_t& rs_new, double dE) { - E += dE; - M += rs_new - rs_old; - -#ifdef DIMENSION - for (D_t i = 0; i < DIMENSION; i++) -#else - for (D_t i = 0; i < D; i++) -#endif - { - ReF[i] += (rs_new - rs_old) * precomputed_cos[v][i]; - ImF[i] += (rs_new - rs_old) * precomputed_sin[v][i]; - } - } - - void plain_site_transformed(v_t v, const X_t& s_old, const X_t& s_new) { - last_cluster_size++; - } - - void ghost_site_transformed(const R_t& r_old, const R_t& r_new) { - } - - void post_cluster(const state_t<R_t, X_t>& s, count_t step, count_t N) { - if (flags & measurement_energy) { - float smaller_E = (float)E; - fwrite(&smaller_E, sizeof(float), 1, files[0]); - } - if (flags & measurement_clusterSize) { - fwrite(&(last_cluster_size), sizeof(uint32_t), 1, files[1]); - } - if (flags & measurement_magnetization) { - write_magnetization(M, files[2]); - } - if (flags & measurement_fourierZero) { - float smaller_X = (float)correlation_length<X_t>(ReF, ImF, D); - fwrite(&smaller_X, sizeof(float), 1, files[3]); - } - - other_f(s, *this); - - } - - ~wolff_research_measurements() { - for (uint8_t i = 0; i < POSSIBLE_MEASUREMENTS; i++) { - if (flags & (1 << i)) { - fclose(files[i]); - } - } - - if (!silent) { - printf("\033[F\033[J"); - } - printf("WOLFF COMPLETE: E = %.2f, S = %" PRIv "\n", E, last_cluster_size); - - free(files); - } -}; - diff --git a/examples/include/randutils b/examples/include/randutils deleted file mode 160000 -Subproject 8486a610a954a8248c12485fb4cfc390a5f5f85 diff --git a/examples/ising.cpp b/examples/ising.cpp new file mode 100644 index 0000000..ffcb7e4 --- /dev/null +++ b/examples/ising.cpp @@ -0,0 +1,82 @@ + +#include <getopt.h> +#include <iostream> +#include <chrono> + +#include "simple_measurement.hpp" + +#include <wolff/models/ising.hpp> +#include <wolff/finite_states.hpp> +#include <wolff.hpp> + +int main(int argc, char *argv[]) { + + // set defaults + N_t N = (N_t)1e4; + D_t D = 2; + L_t L = 128; + double T = 2.26918531421; + double H = 0.0; + + int opt; + + // take command line arguments + while ((opt = getopt(argc, argv, "N:D:L:T:H:")) != -1) { + switch (opt) { + case 'N': // number of steps + N = (N_t)atof(optarg); + break; + case 'D': // dimension + D = atoi(optarg); + break; + case 'L': // linear size + L = atoi(optarg); + break; + case 'T': // temperature + T = atof(optarg); + break; + case 'H': // external field + H = atof(optarg); + break; + default: + exit(EXIT_FAILURE); + } + } + + // define the spin-spin coupling + std::function <double(const ising_t&, const ising_t&)> Z = [] (const ising_t& s1, const ising_t& s2) -> double { + return (double)(s1 * s2); + }; + + // define the spin-field coupling + std::function <double(const ising_t&)> B = [=] (const ising_t& s) -> double { + return H * s; + }; + + // initialize the system + wolff_system<ising_t, ising_t> S(D, L, T, Z, B); + + // initialize the random number generator + auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + std::mt19937 rng{seed}; + + // define function that generates self-inverse rotations + std::function <ising_t(std::mt19937&, const ising_t&)> gen_R = [] (std::mt19937&, const ising_t& s) -> ising_t { + return ising_t(true); + }; + + // initailze the measurement object + simple_measurement A(S); + + // run wolff N times + wolff<ising_t, ising_t>(N, S, gen_R, A, rng); + + // print the result of our measurements + std::cout << "Wolff complete!\nThe average energy per site was " << A.avgE() / S.nv + << ".\nThe average magnetization per site was " << A.avgM() / S.nv + << ".\nThe average cluster size per site was " << A.avgC() / S.nv << ".\n"; + + // exit + return 0; +} + diff --git a/examples/simple_ising.cpp b/examples/simple_ising.cpp deleted file mode 100644 index 24e4ae5..0000000 --- a/examples/simple_ising.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -#include <getopt.h> -#include <iostream> - -#include "include/randutils/randutils.hpp" - -#include <wolff.hpp> - -// define your R_t and X_t. here both are the same, ising_t -class ising_t { - public: - bool x; - - // both X_t and R_t need a default constructor (and destructor, if relevant) - ising_t() : x(false) {} - ising_t(bool x) : x(x) {} - - // R_t needs the member functions - // X_t act(const X_t& s) const {} - // R_t act(const R_t& s) const {} - // to define action on both spins and other transformations - ising_t act(const ising_t& s) const { - if (x) { - return ising_t(!(s.x)); - } else { - return ising_t(s.x); - } - } - - // R_t needs the member functions - // X_t act_inverse(const X_t& s) const {} - // R_t act_inverse(const R_t& s) const {} - // to define action of its inverse on both spins and other transformations - ising_t act_inverse(const ising_t& s) const { - return this->act(s); - } -}; - -// define how measurements should be taken by importing the interface wolff_measurement<R_t, X_t> -class ising_measurements : public wolff_measurement<ising_t, ising_t> { - private: - count_t n; - - double E; - int M; - v_t S; - - double totalE; - double totalM; - double totalS; - - public: - ising_measurements(D_t D, L_t L, double H) { - n = 0; - M = (int)pow(L, D); - E = -D * pow(L, D) - H * pow(L, D); - - totalE = 0; - totalM = 0; - totalS = 0; - } - - void pre_cluster(const state_t<ising_t, ising_t>& s, count_t step, count_t N, v_t v0, const ising_t& R) { - S = 0; - } - - void plain_bond_added(v_t v, const ising_t& s_old, const ising_t& s_new, v_t vn, const ising_t& sn, double dE) { - E += dE; - } - - void ghost_bond_added(v_t v, const ising_t& s_old, const ising_t& s_new, double dE) { - E += dE; - - if (s_old.x) { - M++; - } else { - M--; - } - - if (s_new.x) { - M--; - } else { - M++; - } - } - - void plain_site_transformed(v_t v, const ising_t& s_old, const ising_t& s_new) { - S++; - } - - void ghost_site_transformed(const ising_t& R_old, const ising_t& R_new) { - } - - void post_cluster(const state_t<ising_t, ising_t>& s, count_t step, count_t N) { - totalE += E; - totalM += M; - totalS += S; - n++; - } - - double avgE() { - return totalE / n; - } - - double avgM() { - return totalM / n; - } - - double avgS() { - return totalS / n; - } -}; - -int main(int argc, char *argv[]) { - - // set defaults - count_t N = (count_t)1e4; - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double H = 0.0; - - int opt; - - // take command line arguments - while ((opt = getopt(argc, argv, "N:D:L:T:H:")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field - H = atof(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // define the spin-spin coupling - std::function <double(const ising_t&, const ising_t&)> Z = [] (const ising_t& s1, const ising_t& s2) -> double { - if (s1.x == s2.x) { - return 1.0; - } else { - return -1.0; - } - }; - - // define the spin-field coupling - std::function <double(const ising_t&)> B = [=] (const ising_t& s) -> double { - if (s.x) { - return -H; - } else { - return H; - } - }; - - // initialize the system - state_t<ising_t, ising_t> s(D, L, T, Z, B); - - // initialize the random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define function that generates self-inverse rotations - std::function <ising_t(std::mt19937&, const ising_t&)> gen_R = [] (std::mt19937&, const ising_t& s) -> ising_t { - return ising_t(true); - }; - - // initailze the measurement object - ising_measurements m(D, L, H); - - // run wolff N times - wolff<ising_t, ising_t>(N, s, gen_R, m, rng); - - // print the result of our measurements - std::cout << "Wolff complete!\nThe average energy per site was " << m.avgE() / s.nv - << ".\nThe average magnetization per site was " << m.avgM() / s.nv - << ".\nThe average cluster size per site was " << m.avgS() / s.nv << ".\n"; - - // exit - return 0; -} - diff --git a/examples/simple_measurement.hpp b/examples/simple_measurement.hpp new file mode 100644 index 0000000..2287c58 --- /dev/null +++ b/examples/simple_measurement.hpp @@ -0,0 +1,66 @@ + +#include <wolff/measurement.hpp> + +template <class R_t, class X_t> +class simple_measurement : public wolff_measurement<R_t, X_t> { + private: + N_t n; + + double E; + typename X_t::M_t M; + v_t C; + + double totalE; + typename X_t::F_t totalM; + double totalC; + + public: + simple_measurement(const wolff_system<R_t, X_t>& S) { + n = 0; + M = S.nv * S.s[0]; + E = - (S.ne * S.Z(S.s[0], S.s[0]) + S.nv * S.B(S.s[0])); + + totalE = 0; + totalM = 0.0 * (S.s[0]); + totalC = 0; + } + + void pre_cluster(N_t, N_t, const wolff_system<R_t, X_t>&, v_t, const R_t&) { + C = 0; + } + + void plain_bond_visited(const wolff_system<R_t, X_t>&, v_t, const X_t&, v_t, double dE) { + E += dE; + } + + void ghost_bond_visited(const wolff_system<R_t, X_t>&, v_t, const X_t& s_old, const X_t& s_new, double dE) { + E += dE; + M += s_new - s_old; + } + + void plain_site_transformed(const wolff_system<R_t, X_t>&, v_t, const X_t&) { + C++; + } + + void ghost_site_transformed(const wolff_system<R_t, X_t>&, const R_t&) {} + + void post_cluster(N_t, N_t, const wolff_system<R_t, X_t>&) { + totalE += E; + totalM += M; + totalC += C; + n++; + } + + double avgE() { + return totalE / n; + } + + typename X_t::F_t avgM() { + return totalM / n; + } + + double avgC() { + return totalC / n; + } +}; + diff --git a/examples/src/CMakeLists.txt b/examples/src/CMakeLists.txt deleted file mode 100644 index 3397426..0000000 --- a/examples/src/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ - -add_subdirectory(models) -add_subdirectory(tools) - diff --git a/examples/src/models/CMakeLists.txt b/examples/src/models/CMakeLists.txt deleted file mode 100644 index 0b0c111..0000000 --- a/examples/src/models/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ - -add_subdirectory(ising) -add_subdirectory(On) -add_subdirectory(potts) -add_subdirectory(roughening) - diff --git a/examples/src/models/On/CMakeLists.txt b/examples/src/models/On/CMakeLists.txt deleted file mode 100644 index 1b2e058..0000000 --- a/examples/src/models/On/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ - -add_executable(wolff_planar wolff_On.cpp) -add_executable(wolff_planar_2d_no-field wolff_On.cpp) -add_executable(wolff_heisenberg wolff_On.cpp) - -set_target_properties(wolff_planar PROPERTIES COMPILE_FLAGS "-DN_COMP=2") -set_target_properties(wolff_planar_2d_no-field PROPERTIES COMPILE_FLAGS "-DN_COMP=2 -DDIMENSION=2 -DNOFIELD") -set_target_properties(wolff_heisenberg PROPERTIES COMPILE_FLAGS "-DN_COMP=3") - -find_library(GL NAMES GL) -find_library(GLU NAMES GLU) -find_library(GLUT NAMES glut) - -if (${GLUT} MATCHES "GLUT-NOTFOUND") - target_link_libraries(wolff_planar wolff wolff_examples) - target_link_libraries(wolff_planar_2d_no-field wolff wolff_examples) - target_link_libraries(wolff_heisenberg wolff wolff_examples) -else() - target_compile_definitions(wolff_planar PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_planar_2d_no-field PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_heisenberg PUBLIC HAVE_GLUT) - - target_link_libraries(wolff_planar wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_planar_2d_no-field wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_heisenberg wolff wolff_examples glut GL GLU) -endif() - -install(TARGETS wolff_planar wolff_planar_2d_no-field wolff_heisenberg DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) - diff --git a/examples/src/models/On/wolff_On.cpp b/examples/src/models/On/wolff_On.cpp deleted file mode 100644 index 67f28a5..0000000 --- a/examples/src/models/On/wolff_On.cpp +++ /dev/null @@ -1,269 +0,0 @@ - -#include <getopt.h> -#include <stdio.h> - -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -#include "orthogonal.hpp" -#include "vector.hpp" - -#include <wolff.hpp> -#include <measure.hpp> -#include <colors.h> -#include <randutils/randutils.hpp> - -typedef orthogonal_t <N_COMP, double> orthogonal_R_t; -typedef vector_t <N_COMP, double> vector_R_t; -typedef state_t <orthogonal_R_t, vector_R_t> On_t; - -// angle from the x-axis of a two-vector -double theta(vector_R_t v) { - double x = v[0]; - double y = v[1]; - - double val = atan(y / x); - - if (x < 0.0 && y > 0.0) { - return M_PI + val; - } else if ( x < 0.0 && y < 0.0 ) { - return - M_PI + val; - } else { - return val; - } -} - -double H_modulated(vector_R_t v, int order, double mag) { - return mag * cos(order * theta(v)); -} - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e7; - -#ifdef DIMENSION - D_t D = DIMENSION; -#else - D_t D = 2; -#endif - L_t L = 128; - double T = 2.26918531421; - double *H_vec = (double *)calloc(MAX_Q, sizeof(double)); - - bool silent = false; - bool use_pert = false; - bool N_is_sweeps = false; - bool draw = false; - unsigned int window_size = 512; - - bool modulated_field = false; - unsigned int order = 1; - - int opt; - q_t H_ind = 0; - double epsilon = 1; - -// unsigned char measurement_flags = measurement_energy | measurement_clusterSize; - - unsigned char measurement_flags = 0; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:spe:mo:M:Sdw:")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; -#ifdef DIMENSION - case 'D': // dimension - printf("Dimension was specified at compile time, you can't change it now!\n"); - exit(EXIT_FAILURE); -#else - case 'D': // dimension - D = atoi(optarg); - break; -#endif - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field. nth call couples to state n - H_vec[H_ind] = atof(optarg); - H_ind++; - break; - 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; - case 'm': - modulated_field = true; - break; - case 'M': - measurement_flags ^= 1 << atoi(optarg); - break; - case 'o': - order = atoi(optarg); - break; - case 'S': - N_is_sweeps = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - unsigned long timestamp; - - { - struct timespec spec; - clock_gettime(CLOCK_REALTIME, &spec); - timestamp = spec.tv_sec*1000000000LL + spec.tv_nsec; - } - - const char *pert_type; - - std::function <orthogonal_R_t(std::mt19937&, vector_R_t)> gen_R; - - if (use_pert) { - double Hish; - if (modulated_field) { - Hish = fabs(H_vec[0]); - } else { - double H2 = 0; - for (q_t i = 0; i < N_COMP; i++) { - H2 += pow(H_vec[i], 2); - } - Hish = sqrt(H2); - } - - epsilon = sqrt((N_COMP - 1) * T / (D + Hish / 2)) / 2; - - gen_R = std::bind(generate_rotation_perturbation <N_COMP>, std::placeholders::_1, std::placeholders::_2, epsilon, order); - pert_type = "PERTURB5"; - } else { - gen_R = generate_rotation_uniform <N_COMP>; - pert_type = "UNIFORM"; - } - - FILE *outfile_info = fopen("wolff_metadata.txt", "a"); - - fprintf(outfile_info, "<| \"ID\" -> %lu, \"MODEL\" -> \"%s\", \"q\" -> %d, \"D\" -> %" PRID ", \"L\" -> %" PRIL ", \"NV\" -> %" PRIv ", \"NE\" -> %" PRIv ", \"T\" -> %.15f, \"FIELD_TYPE\" -> ", timestamp, ON_strings[N_COMP], N_COMP, D, L, (v_t)pow(L, D), D * (v_t)pow(L, D), T); - if (modulated_field) { - fprintf(outfile_info, "\"MODULATED\", \"ORDER\" -> %d, \"H\" -> %.15f, ", order, H_vec[0]); - } else { - fprintf(outfile_info, "\"VECTOR\", \"H\" -> {"); - for (q_t i = 0; i < N_COMP; i++) { - fprintf(outfile_info, "%.15f", H_vec[i]); - if (i < N_COMP - 1) { - fprintf(outfile_info, ", "); - } - } - fprintf(outfile_info, "}, "); - } - - fprintf(outfile_info, "\"GENERATOR\" -> \"%s\"", pert_type); - - if (use_pert) { - fprintf(outfile_info, ", \"EPS\" -> %g", epsilon); - } - - fprintf(outfile_info, " |>\n"); - - fclose(outfile_info); - - std::function <void(const On_t&, const wolff_research_measurements<orthogonal_R_t, vector_R_t>&)> other_f; - uint64_t sum_of_clusterSize = 0; - - if (N_is_sweeps) { - other_f = [&] (const On_t& s, const wolff_research_measurements<orthogonal_R_t, vector_R_t>& m) { - sum_of_clusterSize += m.last_cluster_size; - }; - } else if (draw) { -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - other_f = [&] (const On_t& s, const wolff_research_measurements<orthogonal_R_t, vector_R_t>& m) { - glClear(GL_COLOR_BUFFER_BIT); - for (v_t i = 0; i < pow(L, 2); i++) { -#ifdef NOFIELD - vector_R_t v_tmp = s.spins[i]; -#else - vector_R_t v_tmp = s.R.act_inverse(s.spins[i]); -#endif - double thetai = fmod(2 * M_PI + theta(v_tmp), 2 * M_PI); - double saturation = 0.7; - double value = 0.9; - double chroma = saturation * value; - glColor3f(chroma * hue_to_R(thetai) + (value - chroma), chroma * hue_to_G(thetai) + (value - chroma), chroma * hue_to_B(thetai) + (value - chroma)); - glRecti(i / L, i % L, (i / L) + 1, (i % L) + 1); - } - glFlush(); - }; -#endif - } else { - other_f = [] (const On_t& s, const wolff_research_measurements<orthogonal_R_t, vector_R_t>& m) {}; - } - - std::function <double(const vector_R_t&)> H; - - if (modulated_field) { - H = std::bind(H_modulated, std::placeholders::_1, order, H_vec[0]); - } else { - H = std::bind(H_vector <N_COMP, double>, std::placeholders::_1, H_vec); - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - -#ifndef NOFIELD - state_t <orthogonal_R_t, vector_R_t> s(D, L, T, dot <N_COMP, double>, H); -#else - state_t <orthogonal_R_t, vector_R_t> s(D, L, T, dot <N_COMP, double>); -#endif - - wolff_research_measurements<orthogonal_R_t, vector_R_t> m(measurement_flags, timestamp, other_f, s, silent); - - if (N_is_sweeps) { - count_t N_rounds = 0; - printf("\n"); - while (sum_of_clusterSize < N * s.nv) { - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, m.E, m.last_cluster_size); - wolff <orthogonal_R_t, vector_R_t> (N, s, gen_R, m, rng); - N_rounds++; - } - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, m.E, m.last_cluster_size); - } else { - wolff <orthogonal_R_t, vector_R_t> (N, s, gen_R, m, rng); - } - - free(H_vec); - - return 0; -} - diff --git a/examples/src/models/ising/CMakeLists.txt b/examples/src/models/ising/CMakeLists.txt deleted file mode 100644 index 9f4acd4..0000000 --- a/examples/src/models/ising/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ - -add_executable(wolff_ising wolff_ising.cpp) -add_executable(wolff_ising_2d wolff_ising.cpp) -add_executable(wolff_ising_2d_no-field wolff_ising.cpp) -add_executable(wolff_random-field_ising wolff_random-field_ising.cpp) - -set_target_properties(wolff_ising_2d PROPERTIES COMPILE_FLAGS "-DDIMENSION=2") -set_target_properties(wolff_ising_2d_no-field PROPERTIES COMPILE_FLAGS "-DDIMENSION=2 -DNOFIELD") - -find_library(GL NAMES GL) -find_library(GLU NAMES GLU) -find_library(GLUT NAMES glut) - -if (${GLUT} MATCHES "GLUT-NOTFOUND") - target_link_libraries(wolff_ising wolff wolff_examples) - target_link_libraries(wolff_ising_2d wolff wolff_examples) - target_link_libraries(wolff_ising_2d_no-field wolff wolff_examples) - target_link_libraries(wolff_random-field_ising wolff wolff_examples) -else() - target_compile_definitions(wolff_ising PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_ising_2d PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_ising_2d_no-field PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_random-field_ising PUBLIC HAVE_GLUT) - - target_link_libraries(wolff_ising wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_ising_2d wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_ising_2d_no-field wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_random-field_ising wolff wolff_examples glut GL GLU) -endif() - -install(TARGETS wolff_ising wolff_ising_2d wolff_ising_2d_no-field wolff_random-field_ising DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) - diff --git a/examples/src/models/ising/ising.hpp b/examples/src/models/ising/ising.hpp deleted file mode 100644 index 73b06ed..0000000 --- a/examples/src/models/ising/ising.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include <cmath> -#include <stdio.h> - -#include <wolff/types.h> - -// all that is required to use wolff.hpp is a default constructor -class ising_t { - public: - bool x; - - ising_t() : x(false) {} - - // optional constructors for syntactic sugar - ising_t(bool x) : x(x) {} - ising_t(int x) : x((bool)x) {} - - /* below this comment is code required only for using measure.hpp in the - * examples folder, which provides an interface for measuring several - * generic features of models. these require - * - * - an M_t, representing the magnetization or sum of all spins - * - an F_t, representing a double-weighted version of the magnetization - * - the overloaded operator *, which takes a v_t (unsigned int) and returns an M_t - * - the overloaded operator *, which takes a double and returns an F_t - * - the overloaded operator -, which takes another X_t and returns an M_t - */ - - typedef int M_t; - typedef double F_t; - - inline int operator*(v_t a) const { - if (x) { - return -(int)a; - } else { - return (int)a; - } - } - - inline double operator*(double a) const { - if (x) { - return -a; - } else { - return a; - } - } - - inline int operator-(const ising_t &s) const { - if (x == s.x) { - return 0; - } else { - if (x) { - return -2; - } else { - return 2; - } - } - } -}; - -/* using measure.hpp additionally requires a norm_squared function which takes - * an F_t to a double, and a write_magnetization function, which takes an M_t - * and a FILE pointer and appropriately records the contents of the former to - * the latter. - */ - -double norm_squared(double s) { - return pow(s, 2); -} - -void write_magnetization(int M, FILE *outfile) { - fwrite(&M, sizeof(int), 1, outfile); -} - -/* these definitions allow wolff/finite_states.hpp to be invoked and provide - * much faster performance for models whose number of possible spin - * configurations is finite. - */ - -#define N_STATES 2 -const ising_t states[2] = {ising_t(0), ising_t(1)}; -q_t state_to_ind(ising_t state) { return (q_t)state.x; } - diff --git a/examples/src/models/ising/wolff_ising.cpp b/examples/src/models/ising/wolff_ising.cpp deleted file mode 100644 index de04f32..0000000 --- a/examples/src/models/ising/wolff_ising.cpp +++ /dev/null @@ -1,197 +0,0 @@ - -#include <getopt.h> -#include <stdio.h> - -// if you have GLUT installed, you can see graphics! -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -// include your group and spin space -#include "z2.hpp" -#include "ising.hpp" - -// finite_states.h can be included for spin types that have special variables -// defined, and it causes wolff execution to use precomputed bond probabilities -#include <wolff/finite_states.hpp> - -#include <randutils/randutils.hpp> - -// measure.hpp contains useful functions for saving timeseries to files -#include <measure.hpp> - -// include wolff.hpp -#include <wolff.hpp> - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e4; - - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double H = 0.0; - - bool silent = false; - bool draw = false; - bool N_is_sweeps = false; - unsigned int window_size = 512; - - // don't measure anything by default - unsigned char measurement_flags = 0; - - int opt; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:sdw:M:S")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field - H = atof(optarg); - break; - case 's': // don't print anything during simulation. speeds up slightly - silent = true; - break; - case 'S': - N_is_sweeps = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - case 'M': - measurement_flags ^= 1 << atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // get nanosecond timestamp for unique run id - unsigned long timestamp; - - { - struct timespec spec; - clock_gettime(CLOCK_REALTIME, &spec); - timestamp = spec.tv_sec*1000000000LL + spec.tv_nsec; - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define spin-spin coupling - std::function <double(const ising_t&, const ising_t&)> Z = [] (const ising_t& s1, const ising_t& s2) -> double { - if (s1.x == s2.x) { - return 1.0; - } else { - return -1.0; - } - }; - - // define spin-field coupling - std::function <double(const ising_t&)> B = [=] (const ising_t& s) -> double { - if (s.x) { - return -H; - } else { - return H; - } - }; - - // initialize state object -#ifndef NOFIELD - state_t <z2_t, ising_t> s(D, L, T, Z, B); -#else - state_t <z2_t, ising_t> s(D, L, T, Z); -#endif - - // define function that generates self-inverse rotations - std::function <z2_t(std::mt19937&, ising_t)> gen_R = [] (std::mt19937&, const ising_t& s) -> z2_t { - return z2_t(true); - }; - - std::function <void(const state_t<z2_t, ising_t>&, const wolff_research_measurements<z2_t, ising_t>&)> other_f; - uint64_t sum_of_clusterSize = 0; - - if (N_is_sweeps) { - other_f = [&] (const state_t<z2_t, ising_t>& s, const wolff_research_measurements<z2_t, ising_t>& meas) { - sum_of_clusterSize += meas.last_cluster_size; - }; - } else if (draw) { -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - other_f = [] (const state_t <z2_t, ising_t>& s, const wolff_research_measurements<z2_t, ising_t>& meas) { - glClear(GL_COLOR_BUFFER_BIT); - for (v_t i = 0; i < pow(s.L, 2); i++) { -#ifdef NOFIELD - if (s.spins[i].x == false) { -#else - if (s.spins[i].x == s.R.x) { -#endif - glColor3f(0.0, 0.0, 0.0); - } else { - glColor3f(1.0, 1.0, 1.0); - } - glRecti(i / s.L, i % s.L, (i / s.L) + 1, (i % s.L) + 1); - } - glFlush(); - }; -#endif - } else { - other_f = [] (const state_t<z2_t, ising_t>& s, const wolff_research_measurements<z2_t, ising_t>& meas) {}; - } - - wolff_research_measurements<z2_t, ising_t> m(measurement_flags, timestamp, other_f, s, silent); - - // add line to metadata file with run info - { - FILE *outfile_info = fopen("wolff_metadata.txt", "a"); - - fprintf(outfile_info, "<| \"ID\" -> %lu, \"MODEL\" -> \"ISING\", \"q\" -> 2, \"D\" -> %" PRID ", \"L\" -> %" PRIL ", \"NV\" -> %" PRIv ", \"NE\" -> %" PRIv ", \"T\" -> %.15f, \"H\" -> %.15f |>\n", timestamp, s.D, s.L, s.nv, s.ne, T, H); - - fclose(outfile_info); - } - - // run wolff for N cluster flips - if (N_is_sweeps) { - count_t N_rounds = 0; - printf("\n"); - while (sum_of_clusterSize < N * s.nv) { - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, m.E, m.last_cluster_size); - wolff(N, s, gen_R, m, rng); - N_rounds++; - } - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, m.E, m.last_cluster_size); - } else { - wolff(N, s, gen_R, m, rng); - } - - return 0; -} - diff --git a/examples/src/models/ising/wolff_random-field_ising.cpp b/examples/src/models/ising/wolff_random-field_ising.cpp deleted file mode 100644 index ce26b88..0000000 --- a/examples/src/models/ising/wolff_random-field_ising.cpp +++ /dev/null @@ -1,207 +0,0 @@ - -#define SITE_DEPENDENCE - -#include <getopt.h> -#include <stdio.h> - -// if you have GLUT installed, you can see graphics! -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -// include your group and spin space -#include "z2.hpp" -#include "ising.hpp" - -#include <randutils/randutils.hpp> - -// measure.hpp contains useful functions for saving timeseries to files -#include <measure.hpp> - -// include wolff.hpp -#include <wolff.hpp> - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e4; - - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double H = 0.0; - - bool silent = false; - bool draw = false; - bool N_is_sweeps = false; - unsigned int window_size = 512; - - // don't measure anything by default - unsigned char measurement_flags = 0; - - int opt; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:sdw:M:S")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field - H = atof(optarg); - break; - case 's': // don't print anything during simulation. speeds up slightly - silent = true; - break; - case 'S': - N_is_sweeps = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - case 'M': - measurement_flags ^= 1 << atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // get nanosecond timestamp for unique run id - unsigned long timestamp; - - { - struct timespec spec; - clock_gettime(CLOCK_REALTIME, &spec); - timestamp = spec.tv_sec*1000000000LL + spec.tv_nsec; - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define spin-spin coupling - std::function <double(const ising_t&, const ising_t&)> Z = [] (const ising_t& s1, const ising_t& s2) -> double { - if (s1.x == s2.x) { - return 1.0; - } else { - return -1.0; - } - }; - - // create random field - std::vector<double> random_field_values(pow(L, D)); - std::normal_distribution<double> distribution(0.0, H); - for (v_t i = 0; i < pow(L, D); i++) { - random_field_values[i] = distribution(rng); - } - - // define spin-field coupling - std::function <double(v_t, const ising_t&)> B = [&] (v_t v, const ising_t& s) -> double { - if (s.x) { - return -random_field_values[v]; - } else { - return random_field_values[v]; - } - }; - - // initialize state object -#ifndef NOFIELD - state_t <z2_t, ising_t> s(D, L, T, Z, B); -#else - state_t <z2_t, ising_t> s(D, L, T, Z); -#endif - - // define function that generates self-inverse rotations - std::function <z2_t(std::mt19937&, ising_t)> gen_R = [] (std::mt19937&, const ising_t& s) -> z2_t { - return z2_t(true); - }; - - FILE **outfiles = measure_setup_files(measurement_flags, timestamp); - - std::function <void(const state_t<z2_t, ising_t>&)> other_f; - uint64_t sum_of_clusterSize = 0; - - if (N_is_sweeps) { - other_f = [&] (const state_t<z2_t, ising_t>& s) { - sum_of_clusterSize += s.last_cluster_size; - }; - } else if (draw) { -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - other_f = [] (const state_t <z2_t, ising_t>& s) { - glClear(GL_COLOR_BUFFER_BIT); - for (v_t i = 0; i < pow(s.L, 2); i++) { -#ifdef NOFIELD - if (s.spins[i].x == false) { -#else - if (s.spins[i].x == s.R.x) { -#endif - glColor3f(0.0, 0.0, 0.0); - } else { - glColor3f(1.0, 1.0, 1.0); - } - glRecti(i / s.L, i % s.L, (i / s.L) + 1, (i % s.L) + 1); - } - glFlush(); - }; -#endif - } else { - other_f = [] (const state_t<z2_t, ising_t>& s) {}; - } - - std::function <void(const state_t<z2_t, ising_t>&)> measurements = measure_function_write_files(measurement_flags, outfiles, other_f); - - // add line to metadata file with run info - { - FILE *outfile_info = fopen("wolff_metadata.txt", "a"); - - fprintf(outfile_info, "<| \"ID\" -> %lu, \"MODEL\" -> \"ISING\", \"q\" -> 2, \"D\" -> %" PRID ", \"L\" -> %" PRIL ", \"NV\" -> %" PRIv ", \"NE\" -> %" PRIv ", \"T\" -> %.15f, \"H\" -> %.15f |>\n", timestamp, s.D, s.L, s.nv, s.ne, T, H); - - fclose(outfile_info); - } - - // run wolff for N cluster flips - if (N_is_sweeps) { - count_t N_rounds = 0; - printf("\n"); - while (sum_of_clusterSize < N * s.nv) { - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, s.E, s.last_cluster_size); - wolff(N, s, gen_R, measurements, rng, silent); - N_rounds++; - } - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, s.E, s.last_cluster_size); - } else { - wolff(N, s, gen_R, measurements, rng, silent); - } - - measure_free_files(measurement_flags, outfiles); - - return 0; - -} - diff --git a/examples/src/models/ising/z2.hpp b/examples/src/models/ising/z2.hpp deleted file mode 100644 index 19b6c05..0000000 --- a/examples/src/models/ising/z2.hpp +++ /dev/null @@ -1,53 +0,0 @@ - -#pragma once - -#include <wolff/types.h> -#include "ising.hpp" - -/* The minimum definition for a group type R_t to act on a spin type X_t is - * given by the following. - * - * void init(R_t *p); - * void free_spin(R_t r); - * R_t copy(R_t r); - * X_t act(R_t r, X_t x); - * R_t act(R_t r, R_t r); - * X_t act_inverse(R_t r, X_t x); - * R_t act_inverse(R_t r, R_t r); - * - */ - -class z2_t { - public: - bool x; - - z2_t() : x(false) {} - - z2_t(bool x) : x(x) {} - - ising_t act(const ising_t& s) const { - if (x) { - return ising_t(!s.x); - } else { - return ising_t(s.x); - } - } - - z2_t act(const z2_t& r) const { - if (x) { - return z2_t(!r.x); - } else { - return z2_t(r.x); - } - } - - ising_t act_inverse(const ising_t& s) const { - return this->act(s); - } - - z2_t act_inverse(const z2_t& r) const { - return this->act(r); - } -}; - - diff --git a/examples/src/models/potts/CMakeLists.txt b/examples/src/models/potts/CMakeLists.txt deleted file mode 100644 index e78aa6b..0000000 --- a/examples/src/models/potts/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ - -add_executable(wolff_3potts wolff_potts.cpp) -add_executable(wolff_4potts wolff_potts.cpp) -add_executable(wolff_7potts wolff_potts.cpp) -add_executable(wolff_3clock wolff_clock.cpp) -add_executable(wolff_5clock wolff_clock.cpp) - -set_target_properties(wolff_3potts PROPERTIES COMPILE_FLAGS "-DPOTTSQ=3") -set_target_properties(wolff_4potts PROPERTIES COMPILE_FLAGS "-DPOTTSQ=4") -set_target_properties(wolff_7potts PROPERTIES COMPILE_FLAGS "-DPOTTSQ=7") -set_target_properties(wolff_3clock PROPERTIES COMPILE_FLAGS "-DPOTTSQ=3") -set_target_properties(wolff_5clock PROPERTIES COMPILE_FLAGS "-DPOTTSQ=5") - -find_library(GL NAMES GL) -find_library(GLU NAMES GLU) -find_library(GLUT NAMES glut) - -if (${GLUT} MATCHES "GLUT-NOTFOUND") - target_link_libraries(wolff_3potts wolff wolff_examples) - target_link_libraries(wolff_4potts wolff wolff_examples) - target_link_libraries(wolff_7potts wolff wolff_examples) - target_link_libraries(wolff_3clock wolff wolff_examples) - target_link_libraries(wolff_5clock wolff wolff_examples) -else() - target_compile_definitions(wolff_3potts PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_4potts PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_7potts PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_3clock PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_5clock PUBLIC HAVE_GLUT) - - target_link_libraries(wolff_3potts wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_4potts wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_7potts wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_3clock wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_5clock wolff wolff_examples glut GL GLU) -endif() - -install(TARGETS wolff_3potts wolff_4potts wolff_7potts wolff_3clock wolff_5clock DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) - diff --git a/examples/src/models/potts/wolff_clock.cpp b/examples/src/models/potts/wolff_clock.cpp deleted file mode 100644 index 0706cc5..0000000 --- a/examples/src/models/potts/wolff_clock.cpp +++ /dev/null @@ -1,149 +0,0 @@ - -#include <getopt.h> - -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -// include your group and spin space -#include "dihedral.hpp" -#include "potts.hpp" -#include <colors.h> -#include <measure.hpp> - -// hack to speed things up considerably -#define N_STATES POTTSQ -#include <wolff/finite_states.hpp> - -#include <randutils/randutils.hpp> - -// include wolff.hpp -#include <wolff.hpp> - -typedef state_t <dihedral_t<POTTSQ>, potts_t<POTTSQ>> sim_t; - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e4; - - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double *H_vec = (double *)calloc(MAX_Q, sizeof(double)); - - bool silent = false; - bool draw = false; - unsigned int window_size = 512; - - int opt; - q_t H_ind = 0; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:sdw:")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field. nth call couples to state n - H_vec[H_ind] = atof(optarg); - H_ind++; - break; - case 's': // don't print anything during simulation. speeds up slightly - silent = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define spin-spin coupling - std::function <double(const potts_t<POTTSQ>&, const potts_t<POTTSQ>&)> Z = [] (const potts_t<POTTSQ>& s1, const potts_t<POTTSQ>& s2) -> double { - return cos(2 * M_PI * (double)(s1.x + POTTSQ - s2.x) / (double)POTTSQ); - }; - - // define spin-field coupling - std::function <double(const potts_t<POTTSQ>&)> B = [=] (const potts_t<POTTSQ>& s) -> double { - return H_vec[s.x]; - }; - - // initialize state object - state_t <dihedral_t<POTTSQ>, potts_t<POTTSQ>> s(D, L, T, Z, B); - - // define function that generates self-inverse rotations - std::function <dihedral_t<POTTSQ>(std::mt19937&, potts_t<POTTSQ>)> gen_R = [] (std::mt19937& r, potts_t<POTTSQ> v) -> dihedral_t<POTTSQ> { - dihedral_t<POTTSQ> rot; - rot.is_reflection = true; - std::uniform_int_distribution<q_t> dist(0, POTTSQ - 2); - q_t x = dist(r); - rot.x = (2 * v.x + x + 1) % POTTSQ; - - return rot; - }; - - // define function that updates any number of measurements - std::function <void(const sim_t&, const wolff_research_measurements<dihedral_t<POTTSQ>, potts_t<POTTSQ>>&)> measurement; - - if (!draw) { - // a very simple example: measure the average magnetization - measurement = [&] (const sim_t& s, const wolff_research_measurements<dihedral_t<POTTSQ>, potts_t<POTTSQ>>&) { - }; - } else { - // a more complex example: measure the average magnetization, and draw the spin configuration to the screen - -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - measurement = [&] (const sim_t& s, const wolff_research_measurements<dihedral_t<POTTSQ>, potts_t<POTTSQ>>&) { - glClear(GL_COLOR_BUFFER_BIT); - for (v_t i = 0; i < pow(L, 2); i++) { - potts_t<POTTSQ> tmp_s = s.R.act_inverse(s.spins[i]); - glColor3f(hue_to_R(tmp_s.x * 2 * M_PI / POTTSQ), hue_to_G(tmp_s.x * 2 * M_PI / POTTSQ), hue_to_B(tmp_s.x * 2 * M_PI / POTTSQ)); - glRecti(i / L, i % L, (i / L) + 1, (i % L) + 1); - } - glFlush(); - }; -#endif - } - - wolff_research_measurements<dihedral_t<POTTSQ>, potts_t<POTTSQ>> m(0, 0, measurement, s, silent); - - // run wolff for N cluster flips - wolff(N, s, gen_R, m, rng); - - // free the random number generator - - return 0; - -} - diff --git a/examples/src/models/potts/wolff_potts.cpp b/examples/src/models/potts/wolff_potts.cpp deleted file mode 100644 index 7b92ac1..0000000 --- a/examples/src/models/potts/wolff_potts.cpp +++ /dev/null @@ -1,210 +0,0 @@ - -#include <getopt.h> -#include <stdio.h> - -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -// include your group and spin space -#include "symmetric.hpp" -#include "potts.hpp" - -// hack to speed things up considerably -#define N_STATES POTTSQ -#include <wolff/finite_states.hpp> - -// include wolff.h -#include <measure.hpp> -#include <colors.h> -#include <randutils/randutils.hpp> -#include <wolff.hpp> - -typedef state_t <symmetric_t<POTTSQ>, potts_t<POTTSQ>> sim_t; - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e4; - - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double *H_vec = (double *)calloc(MAX_Q, sizeof(double)); - - bool silent = false; - bool draw = false; - bool N_is_sweeps = false; - unsigned int window_size = 512; - - // don't measure anything by default - unsigned char measurement_flags = 0; - - int opt; - q_t H_ind = 0; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:sdw:M:S")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field. nth call couples to state n - H_vec[H_ind] = atof(optarg); - H_ind++; - break; - case 's': // don't print anything during simulation. speeds up slightly - silent = true; - break; - case 'S': - N_is_sweeps = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - case 'M': - measurement_flags ^= 1 << atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // get nanosecond timestamp for unique run id - unsigned long timestamp; - - { - struct timespec spec; - clock_gettime(CLOCK_REALTIME, &spec); - timestamp = spec.tv_sec*1000000000LL + spec.tv_nsec; - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define spin-spin coupling - std::function <double(const potts_t<POTTSQ>&, const potts_t<POTTSQ>&)> Z = [] (const potts_t<POTTSQ>& s1, const potts_t<POTTSQ>& s2) -> double { - if (s1.x == s2.x) { - return 1.0; - } else { - return 0.0; - } - }; - - // define spin-field coupling - std::function <double(const potts_t<POTTSQ> &)> B = [=] (const potts_t<POTTSQ>& s) -> double { - return H_vec[s.x]; - }; - - // initialize state object - state_t <symmetric_t<POTTSQ>, potts_t<POTTSQ>> s(D, L, T, Z, B); - - // define function that generates self-inverse rotations - std::function <symmetric_t<POTTSQ>(std::mt19937&, potts_t<POTTSQ>)> gen_R = [] (std::mt19937& r, potts_t<POTTSQ> v) -> symmetric_t<POTTSQ> { - symmetric_t<POTTSQ> rot; - - std::uniform_int_distribution<q_t> dist(0, POTTSQ - 2); - q_t j = dist(r); - q_t swap_v; - if (j < v.x) { - swap_v = j; - } else { - swap_v = j + 1; - } - - rot[v.x] = swap_v; - rot[swap_v] = v.x; - - return rot; - }; - - std::function <void(const sim_t&, const wolff_research_measurements<symmetric_t<POTTSQ>, potts_t<POTTSQ>>&)> other_f; - uint64_t sum_of_clusterSize = 0; - - if (N_is_sweeps) { - other_f = [&] (const sim_t& s, const wolff_research_measurements<symmetric_t<POTTSQ>, potts_t<POTTSQ>>& m) { - sum_of_clusterSize += m.last_cluster_size; - }; - } else if (draw) { -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - other_f = [] (const sim_t& s, const wolff_research_measurements<symmetric_t<POTTSQ>, potts_t<POTTSQ>>& m) { - glClear(GL_COLOR_BUFFER_BIT); - for (v_t i = 0; i < pow(s.L, 2); i++) { - potts_t<POTTSQ> tmp_s = s.R.act_inverse(s.spins[i]); - glColor3f(hue_to_R(tmp_s.x * 2 * M_PI / POTTSQ), hue_to_G(tmp_s.x * 2 * M_PI / POTTSQ), hue_to_B(tmp_s.x * 2 * M_PI / POTTSQ)); - glRecti(i / s.L, i % s.L, (i / s.L) + 1, (i % s.L) + 1); - } - glFlush(); - }; -#endif - } else { - other_f = [] (const sim_t& s, const wolff_research_measurements<symmetric_t<POTTSQ>, potts_t<POTTSQ>>& m) {}; - } - - wolff_research_measurements<symmetric_t<POTTSQ>, potts_t<POTTSQ>> m(measurement_flags, timestamp, other_f, s, silent); - - // add line to metadata file with run info - { - FILE *outfile_info = fopen("wolff_metadata.txt", "a"); - - fprintf(outfile_info, "<| \"ID\" -> %lu, \"MODEL\" -> \"POTTS\", \"q\" -> %d, \"D\" -> %" PRID ", \"L\" -> %" PRIL ", \"NV\" -> %" PRIv ", \"NE\" -> %" PRIv ", \"T\" -> %.15f, \"H\" -> {", timestamp, POTTSQ, s.D, s.L, s.nv, s.ne, T); - - for (q_t i = 0; i < POTTSQ; i++) { - fprintf(outfile_info, "%.15f", H_vec[i]); - if (i < POTTSQ - 1) { - fprintf(outfile_info, ", "); - } - } - - fprintf(outfile_info, "} |>\n"); - - fclose(outfile_info); - } - - // run wolff for N cluster flips - if (N_is_sweeps) { - count_t N_rounds = 0; - printf("\n"); - while (sum_of_clusterSize < N * s.nv) { - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, m.E, m.last_cluster_size); - wolff(N, s, gen_R, m, rng); - N_rounds++; - } - printf("\033[F\033[J\033[F\033[JWOLFF: sweep %" PRIu64 " / %" PRIu64 ": E = %.2f, S = %" PRIv "\n\n", (count_t)((double)sum_of_clusterSize / (double)s.nv), N, m.E, m.last_cluster_size); - } else { - wolff(N, s, gen_R, m, rng); - } - - // free the random number generator - free(H_vec); - - return 0; - -} - diff --git a/examples/src/models/roughening/CMakeLists.txt b/examples/src/models/roughening/CMakeLists.txt deleted file mode 100644 index 163a0b9..0000000 --- a/examples/src/models/roughening/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -add_executable(wolff_dgm wolff_dgm.cpp) -add_executable(wolff_cgm wolff_cgm.cpp) - -find_library(GL NAMES GL) -find_library(GLU NAMES GLU) -find_library(GLUT NAMES glut) - -if (${GLUT} MATCHES "GLUT-NOTFOUND") - target_link_libraries(wolff_dgm wolff wolff_examples) - target_link_libraries(wolff_cgm wolff wolff_examples) -else() - target_compile_definitions(wolff_dgm PUBLIC HAVE_GLUT) - target_compile_definitions(wolff_cgm PUBLIC HAVE_GLUT) - - target_link_libraries(wolff_dgm wolff wolff_examples glut GL GLU) - target_link_libraries(wolff_cgm wolff wolff_examples glut GL GLU) -endif() - -install(TARGETS wolff_dgm wolff_cgm DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) - diff --git a/examples/src/models/roughening/height.hpp b/examples/src/models/roughening/height.hpp deleted file mode 100644 index 4023063..0000000 --- a/examples/src/models/roughening/height.hpp +++ /dev/null @@ -1,75 +0,0 @@ - -#pragma once - -#include <cmath> -#include <stdio.h> - -#include <wolff/types.h> - -/* The following is the minimum definition of a spin class. - * - * The class must contain an M_t and an F_t for holding the sum of an - * integer number of spins and a double-weighted number of spins, - * respectively. - * - * void init(X_t *p); - * void free_spin(X_t p); - * void free_spin(M_t p); - * void free_spin(F_t p); - * X_t copy(X_t x); - * void add(M_t *x1, int factor, X_t x2); - * void add(F_t *x1, double factor, X_t x2); - * M_t scalar_multiple(int factor, X_t x); - * F_t scalar_multiple(double factor, X_t x); - * double norm_squared(F_t x); - * void write_magnetization(M_t M, FILE *outfile); - * - */ - -template <class T> -struct height_t { - T x; - - typedef T M_t; - typedef double F_t; - - height_t() : x(0) {} - - height_t(T x) : x(x) {} - - inline T operator*(v_t a) const { - return x * a; - } - - inline double operator*(double a) const { - return x * a; - } - - inline T operator-(const height_t& h) const { - return x - h.x; - } -}; - -template <class T> -inline T& operator+=(T& M, const height_t<T> &h) { - M += h.x; - - return M; -} - -template <class T> -inline T& operator-=(T& M, const height_t<T> &h) { - M -= h.x; - - return M; -} - -double norm_squared(double h) { - return pow(h, 2); -} - -template <class T> -void write_magnetization(T M, FILE *outfile) { - fwrite(&M, sizeof(T), 1, outfile); -} - diff --git a/examples/src/models/roughening/wolff_cgm.cpp b/examples/src/models/roughening/wolff_cgm.cpp deleted file mode 100644 index 65f8d66..0000000 --- a/examples/src/models/roughening/wolff_cgm.cpp +++ /dev/null @@ -1,167 +0,0 @@ - -#include <getopt.h> - -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -// include your group and spin space -#include "dihedral_inf.hpp" -#include "height.hpp" - -#include <randutils/randutils.hpp> - -// include wolff.h -#include <wolff.hpp> - -typedef state_t <dihedral_inf_t<double>, height_t<double>> sim_t; - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e4; - - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double H = 0; - - bool silent = false; - bool draw = false; - unsigned int window_size = 512; - double epsilon = 1; - - int opt; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:sdw:e:")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field. nth call couples to state n - H = atof(optarg); - break; - case 'e': // external field. nth call couples to state n - epsilon = atof(optarg); - break; - case 's': // don't print anything during simulation. speeds up slightly - silent = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define spin-spin coupling - std::function <double(const height_t<double>&, const height_t<double>&)> Z = [] (const height_t<double>& h1, const height_t<double>& h2) -> double { - return -pow(h1.x - h2.x, 2); - }; - - // define spin-field coupling - std::function <double(height_t<double>)> B = [=] (height_t<double> h) -> double { - return -H * pow(h.x, 2);; - }; - - // initialize state object - sim_t s(D, L, T, Z, B); - - // define function that generates self-inverse rotations - std::function <dihedral_inf_t<double>(std::mt19937&, height_t<double>)> gen_R = [=] (std::mt19937& r, height_t<double> h) -> dihedral_inf_t<double> { - dihedral_inf_t<double> rot; - rot.is_reflection = true; - std::normal_distribution<double> dist(0.0,1.0); - - double amount = epsilon * dist(r); - - rot.x = 2 * h.x + amount; - - return rot; - }; - - // define function that updates any number of measurements - std::function <void(const sim_t&)> measurement; - - double average_M = 0; - if (!draw) { - // a very simple example: measure the average magnetization - measurement = [&] (const sim_t& s) { - average_M += (double)s.M / (double)N / (double)s.nv; - }; - } else { - // a more complex example: measure the average magnetization, and draw the spin configuration to the screen - -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - measurement = [&] (const sim_t& s) { - average_M += (double)s.M / (double)N / (double)s.nv; - glClear(GL_COLOR_BUFFER_BIT); - double max_h = INT64_MIN; - double min_h = INT64_MAX; - for (v_t i = 0; i < pow(L, 2); i++) { - double cur_h = (s.R.act_inverse(s.spins[i])).x; - if (cur_h < min_h) { - min_h = cur_h; - } - if (cur_h > max_h) { - max_h = cur_h; - } - } - - for (v_t i = 0; i < pow(L, 2); i++) { - double cur_h = (s.R.act_inverse(s.spins[i])).x; - double mag = ((double)(cur_h - min_h)) / ((double)(max_h - min_h)); - glColor3f(mag, mag, mag); - glRecti(i / L, i % L, (i / L) + 1, (i % L) + 1); - } - glFlush(); - }; -#endif - } - - // run wolff for N cluster flips - wolff(N, s, gen_R, measurement, rng, silent); - - // tell us what we found! - printf("%" PRIcount " DGM runs completed. D = %" PRID ", L = %" PRIL ", T = %g, H = %g, <M> = %g\n", N, D, L, T, H, average_M); - - // free the random number generator - - if (draw) { - } - - return 0; - -} - diff --git a/examples/src/models/roughening/wolff_dgm.cpp b/examples/src/models/roughening/wolff_dgm.cpp deleted file mode 100644 index 8395382..0000000 --- a/examples/src/models/roughening/wolff_dgm.cpp +++ /dev/null @@ -1,164 +0,0 @@ - -#include <getopt.h> - -#ifdef HAVE_GLUT -#include <GL/glut.h> -#endif - -// include your group and spin space -#include "dihedral_inf.hpp" -#include "height.hpp" - -#include <randutils/randutils.hpp> - -// include wolff.h -#include <wolff.hpp> - -typedef state_t <dihedral_inf_t<int64_t>, height_t<int64_t>> sim_t; - -int main(int argc, char *argv[]) { - - count_t N = (count_t)1e4; - - D_t D = 2; - L_t L = 128; - double T = 2.26918531421; - double H = 0; - - bool silent = false; - bool draw = false; - unsigned int window_size = 512; - uint64_t epsilon = 1; - - int opt; - - while ((opt = getopt(argc, argv, "N:D:L:T:H:sdw:e:")) != -1) { - switch (opt) { - case 'N': // number of steps - N = (count_t)atof(optarg); - break; - case 'D': // dimension - D = atoi(optarg); - break; - case 'L': // linear size - L = atoi(optarg); - break; - case 'T': // temperature - T = atof(optarg); - break; - case 'H': // external field. nth call couples to state n - H = atof(optarg); - break; - case 'e': // external field. nth call couples to state n - epsilon = atof(optarg); - break; - case 's': // don't print anything during simulation. speeds up slightly - silent = true; - break; - case 'd': -#ifdef HAVE_GLUT - draw = true; - break; -#else - printf("You didn't compile this with the glut library installed!\n"); - exit(EXIT_FAILURE); -#endif - case 'w': - window_size = atoi(optarg); - break; - default: - exit(EXIT_FAILURE); - } - } - - // initialize random number generator - randutils::auto_seed_128 seeds; - std::mt19937 rng{seeds}; - - // define spin-spin coupling - std::function <double(const height_t<int64_t>&, const height_t<int64_t>&)> Z = [] (const height_t<int64_t>& h1, const height_t<int64_t>& h2) -> double { - return -pow(h1.x - h2.x, 2); - }; - - // define spin-field coupling - std::function <double(const height_t<int64_t> &)> B = [=] (const height_t<int64_t>& h) -> double { - return -H * pow(h.x, 2);; - }; - - // initialize state object - sim_t s(D, L, T, Z, B); - - // define function that generates self-inverse rotations - std::function <dihedral_inf_t<int64_t>(std::mt19937&, height_t<int64_t>)> gen_R = [=] (std::mt19937& r, height_t<int64_t> h) -> dihedral_inf_t<int64_t> { - dihedral_inf_t<int64_t> rot; - rot.is_reflection = true; - - std::uniform_int_distribution<int64_t> dist(-epsilon,epsilon); - - rot.x = 2 * h.x + dist(r); - - return rot; - }; - - // define function that updates any number of measurements - std::function <void(const sim_t&)> measurement; - - double average_M = 0; - if (!draw) { - // a very simple example: measure the average magnetization - measurement = [&] (const sim_t& s) { - average_M += (double)s.M / (double)N / (double)s.nv; - }; - } else { - // a more complex example: measure the average magnetization, and draw the spin configuration to the screen - -#ifdef HAVE_GLUT - // initialize glut - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); - glutInitWindowSize(window_size, window_size); - glutCreateWindow("wolff"); - glClearColor(0.0,0.0,0.0,0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0.0, L, 0.0, L); - - measurement = [&] (const sim_t& s) { - average_M += (double)s.M / (double)N / (double)s.nv; - glClear(GL_COLOR_BUFFER_BIT); - int64_t max_h = INT64_MIN; - int64_t min_h = INT64_MAX; - for (v_t i = 0; i < pow(L, 2); i++) { - int64_t cur_h = (s.R.act_inverse(s.spins[i])).x; - if (cur_h < min_h) { - min_h = cur_h; - } - if (cur_h > max_h) { - max_h = cur_h; - } - } - - for (v_t i = 0; i < pow(L, 2); i++) { - int64_t cur_h = (s.R.act_inverse(s.spins[i])).x; - double mag = ((double)(cur_h - min_h)) / ((double)(max_h - min_h)); - glColor3f(mag, mag, mag); - glRecti(i / L, i % L, (i / L) + 1, (i % L) + 1); - } - glFlush(); - }; -#endif - } - - // run wolff for N cluster flips - wolff(N, s, gen_R, measurement, rng, silent); - - // tell us what we found! - printf("%" PRIcount " DGM runs completed. D = %" PRID ", L = %" PRIL ", T = %g, H = %g, <M> = %g\n", N, D, L, T, H, average_M); - - if (draw) { - } - - return 0; - -} - diff --git a/examples/src/tools/CMakeLists.txt b/examples/src/tools/CMakeLists.txt deleted file mode 100644 index 4a6c1a0..0000000 --- a/examples/src/tools/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ - -find_library(fftw REQUIRED NAMES fftw3) - -add_executable(analyze_correlations analyze_correlations.cpp) - -target_link_libraries(analyze_correlations fftw3 wolff) - -install(TARGETS analyze_correlations DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) - diff --git a/examples/src/tools/analyze_correlations.cpp b/examples/src/tools/analyze_correlations.cpp deleted file mode 100644 index abeaff3..0000000 --- a/examples/src/tools/analyze_correlations.cpp +++ /dev/null @@ -1,486 +0,0 @@ - -#include <wolff/types.h> -#include <cmath> -#include <cstring> -#include <stdio.h> -#include <stdlib.h> -#include <getopt.h> -#include <fftw3.h> - -template <class T> -double mean(int N, T *data) { - double total = 0; - for (int i = 0; i < N; i++) { - total += (double)data[i]; - } - - return total / N; -} - -double squared_mean(int N, double *data) { - double total = 0; - for (int i = 0; i < N; i++) { - total += pow(data[i], 2); - } - - return total / N; -} - -double central_moment(int N, double *data, double mean, int m) { - double total = 0; - for (int i = 0; i < N; i++) { - total += pow(data[i] - mean, m); - } - - return total / N; -} - -void compute_OO(int N, fftw_plan forward_plan, double *forward_data, fftw_plan reverse_plan, double *reverse_data) { - - fftw_execute(forward_plan); - - reverse_data[0] = forward_data[0] * forward_data[0]; - reverse_data[N / 2] = forward_data[N/2] * forward_data[N/2]; - - for (count_t i = 1; i < N / 2; i++) { - reverse_data[i] = pow(forward_data[i], 2) + pow(forward_data[N - i], 2); - reverse_data[N - i] = 0; - } - - fftw_execute(reverse_plan); - -} - -double finite_energy(q_t nb, double *J, q_t q, double *H, v_t nv, v_t ne, uint32_t *bo, uint32_t *so) { - double energy = 0; - - v_t tot = 0; - for (q_t i = 0; i < nb - 1; i++) { - energy -= J[i] * bo[i]; - tot += bo[i]; - } - - energy -= J[nb - 1] * (ne - tot); - - tot = 0; - for (q_t i = 0; i < q - 1; i++) { - energy -= H[i] * so[i]; - tot += so[i]; - } - - energy -= H[q - 1] * (nv - tot); - - return energy; -} - -int main (int argc, char *argv[]) { - count_t drop = (count_t)1e4; - count_t length = (count_t)1e4; - bool speedy_drop = false; - bool from_stdin = false; - bool oldstyle = false; - - int opt; - - while ((opt = getopt(argc, argv, "d:l:spo")) != -1) { - switch (opt) { - case 'd': - drop = (count_t)atof(optarg); - break; - case 'l': - length = (count_t)atof(optarg); - break; - case 's': - speedy_drop = true; - break; - case 'p': - from_stdin = true; - break; - case 'o': - oldstyle = true; - break; - default: - exit(EXIT_FAILURE); - } - } - FILE *metadata; - - fftw_set_timelimit(1); - - if (from_stdin) { - metadata = stdin; - } else { - metadata = fopen("wolff_metadata.txt", "r"); - } - - if (metadata == NULL) { - printf("Metadata file not found. Make sure you are in the correct directory!\n"); - exit(EXIT_FAILURE); - } - - unsigned long id; - char *model = (char *)malloc(32 * sizeof(char)); - - if (model == NULL) { - printf("Malloc failed.\n"); - exit(EXIT_FAILURE); - } - - q_t q; - D_t D; - L_t L; - v_t nv, ne; - - while (EOF != fscanf(metadata, "<| \"ID\" -> %lu, \"MODEL\" -> \"%[^\"]\", \"q\" -> %" SCNq ", \"D\" -> %" SCND ", \"L\" -> %" SCNL ", \"NV\" -> %" SCNv ", \"NE\" -> %" SCNv ", ", &id, model, &q, &D, &L, &nv, &ne)) { - - printf("%lu: Processing...\n", id); - -// bool is_finite = 0 == strcmp(model, "ISING") || 0 == strcmp(model, "POTTS") || 0 == strcmp(model, "CLOCK"); - - if (oldstyle) { - q_t nb; - double T; - fscanf(metadata, "\"NB\" -> %" SCNq ", \"T\" -> %lf, \"J\" -> {", &nb, &T); - double *J = (double *)malloc(nb * sizeof(double)); - double *H = (double *)malloc(q * sizeof(double)); - - if (J == NULL || H == NULL) { - printf("%lu: Malloc failed.\n", id); - break; - } - - for (q_t i = 0; i < nb - 1; i++) { - fscanf(metadata, "%lf, ", &(J[i])); - } - fscanf(metadata, "%lf}, \"H\" -> {", &(J[nb - 1])); - for (q_t i = 0; i < q - 1; i++) { - fscanf(metadata, "%lf, ", &(H[i])); - } - fscanf(metadata, "%lf} |>\n", &(H[q - 1])); - - char *filename_M = (char *)malloc(128 * sizeof(char)); - char *filename_B = (char *)malloc(128 * sizeof(char)); - char *filename_S = (char *)malloc(128 * sizeof(char)); - - if (filename_M == NULL || filename_B == NULL || filename_S == NULL) { - printf("%lu: Malloc failed.\n", id); - break; - } - - sprintf(filename_M, "wolff_%lu_M.dat", id); - sprintf(filename_B, "wolff_%lu_B.dat", id); - sprintf(filename_S, "wolff_%lu_S.dat", id); - - FILE *file_M = fopen(filename_M, "rb"); - FILE *file_B = fopen(filename_B, "rb"); - FILE *file_S = fopen(filename_S, "rb"); - - if (file_M == NULL || file_B == NULL || file_S == NULL) { - printf("%lu: Opening data file failed.\n", id); - break; - } - - fseek(file_S, 0, SEEK_END); - unsigned long N = ftell(file_S) / sizeof(uint32_t); - fseek(file_S, 0, SEEK_SET); - - if (speedy_drop) { - drop = N - pow(2, floor(log(N) / log(2))); - } else { - if (N % 2 == 1 && drop % 2 == 0) { - drop++; // make sure M is even - } - } - - if (N <= drop) { - printf("\033[F%lu: Number of steps %lu is less than %" PRIcount ", nothing done.\n", id, N, drop); - } else { - int M = N - drop; - - double M_f = (double)M; - - if (length > M) { - length = M; - } - - double *forward_data = (double *)fftw_malloc(M * sizeof(double)); - fftw_plan forward_plan = fftw_plan_r2r_1d(M, forward_data, forward_data, FFTW_R2HC, 0); - double *reverse_data = (double *)fftw_malloc(M * sizeof(double)); - fftw_plan reverse_plan = fftw_plan_r2r_1d(M, reverse_data, reverse_data, FFTW_HC2R, 0); - - - uint32_t *data_S = (uint32_t *)malloc(N * sizeof(uint32_t)); - fread(data_S, N, sizeof(uint32_t), file_S); - for (count_t i = 0; i < M; i++) { - forward_data[i] = (double)data_S[drop + i]; - } - free(data_S); - double mean_S = mean(M, forward_data); - double squaredMean_S = squared_mean(M, forward_data); - double moment2_S = central_moment(M, forward_data, mean_S, 2); - double moment4_S = central_moment(M, forward_data, mean_S, 4); - - compute_OO(M, forward_plan, forward_data, reverse_plan, reverse_data); - - sprintf(filename_S, "wolff_%lu_S_OO.dat", id); - - FILE *file_S = fopen(filename_S, "wb"); - fwrite(&M_f, sizeof(double), 1, file_S); - fwrite(&mean_S, sizeof(double), 1, file_S); - fwrite(&squaredMean_S, sizeof(double), 1, file_S); - fwrite(&moment2_S, sizeof(double), 1, file_S); - fwrite(&moment4_S, sizeof(double), 1, file_S); - fwrite(reverse_data, sizeof(double), length, file_S); - fclose(file_S); - - uint32_t *data_B = (uint32_t *)malloc((nb - 1) * N * sizeof(uint32_t)); - uint32_t *data_M = (uint32_t *)malloc((q - 1) * N * sizeof(uint32_t)); - fread(data_B, N * (nb - 1), sizeof(uint32_t), file_B); - fread(data_M, N * (q - 1), sizeof(uint32_t), file_M); - - for (count_t i = 0; i < M; i++) { - forward_data[i] = finite_energy(nb, J, q, H, nv, ne, data_B + (nb - 1) * (drop + i), data_M + (q - 1) * (drop + i)); - } - - double mean_E = mean(M, forward_data); - double squaredMean_E = squared_mean(M, forward_data); - double moment2_E = central_moment(M, forward_data, mean_E, 2); - double moment4_E = central_moment(M, forward_data, mean_E, 4); - - free(data_B); - free(data_M); - - compute_OO(M, forward_plan, forward_data, reverse_plan, reverse_data); - - sprintf(filename_B, "wolff_%lu_E_OO.dat", id); - - FILE *file_E = fopen(filename_B, "wb"); - fwrite(&M_f, sizeof(double), 1, file_E); - fwrite(&mean_E, sizeof(double), 1, file_E); - fwrite(&squaredMean_E, sizeof(double), 1, file_E); - fwrite(&moment2_E, sizeof(double), 1, file_E); - fwrite(&moment4_E, sizeof(double), 1, file_E); - fwrite(reverse_data, sizeof(double), length, file_E); - fclose(file_E); - - printf("\033[F%lu: Correlation functions for %d steps written.\n", id, M); - - fftw_destroy_plan(forward_plan); - fftw_destroy_plan(reverse_plan); - fftw_free(forward_data); - fftw_free(reverse_data); - - } - - fclose(file_M); - fclose(file_B); - fclose(file_S); - - free(J); - free(H); - - free(filename_S); - free(filename_B); - free(filename_M); - - } else { - char *junk = (char *)malloc(1024 * sizeof(char)); - fscanf(metadata, "%[^\n]\n", junk); // throw away the rest of the line, we don't need it - free(junk); - - char *filename_E = (char *)malloc(128 * sizeof(char)); - char *filename_F = (char *)malloc(128 * sizeof(char)); - char *filename_M = (char *)malloc(128 * sizeof(char)); - char *filename_S = (char *)malloc(128 * sizeof(char)); - - sprintf(filename_E, "wolff_%lu_E.dat", id); - sprintf(filename_F, "wolff_%lu_F.dat", id); - sprintf(filename_M, "wolff_%lu_M.dat", id); - sprintf(filename_S, "wolff_%lu_S.dat", id); - - FILE *file_E = fopen(filename_E, "rb"); - FILE *file_F = fopen(filename_F, "rb"); - FILE *file_M = fopen(filename_M, "rb"); - FILE *file_S = fopen(filename_S, "rb"); - - fseek(file_S, 0, SEEK_END); - unsigned long N = ftell(file_S) / sizeof(uint32_t); - fseek(file_S, 0, SEEK_SET); - - if (speedy_drop) { - drop = N - pow(2, floor(log(N) / log(2))); - } else { - if (N % 2 == 1 && drop % 2 == 0) { - drop++; // make sure M is even - } - } - - if (N <= drop) { - printf("\033[F%lu: Number of steps %lu is less than %" PRIcount ", nothing done.\n", id, N, drop); - } else { - int M = N - drop; - double M_f = (double)M; - - if (length > M) { - length = M; - } - - double *forward_data = (double *)fftw_malloc(M * sizeof(double)); - fftw_plan forward_plan = fftw_plan_r2r_1d(M, forward_data, forward_data, FFTW_R2HC, 0); - - double *reverse_data = (double *)fftw_malloc(M * sizeof(double)); - fftw_plan reverse_plan = fftw_plan_r2r_1d(M, reverse_data, reverse_data, FFTW_HC2R, 0); - - if (file_S != NULL) { - uint32_t *data_S = (uint32_t *)malloc(N * sizeof(uint32_t)); - - fread(data_S, sizeof(uint32_t), N, file_S); - fclose(file_S); - - for (int i = 0; i < M; i++) { - forward_data[i] = (double)data_S[drop + i]; - } - free(data_S); - - double mean_S = mean(M, forward_data); - double squaredMean_S = squared_mean(M, forward_data); - double moment2_S = central_moment(M, forward_data, mean_S, 2); - double moment4_S = central_moment(M, forward_data, mean_S, 4); - - compute_OO(M, forward_plan, forward_data, reverse_plan, reverse_data); - - sprintf(filename_S, "wolff_%lu_S_OO.dat", id); - FILE *file_S_new = fopen(filename_S, "wb"); - fwrite(&M_f, sizeof(double), 1, file_S_new); - fwrite(&mean_S, sizeof(double), 1, file_S_new); - fwrite(&squaredMean_S, sizeof(double), 1, file_S_new); - fwrite(&moment2_S, sizeof(double), 1, file_S_new); - fwrite(&moment4_S, sizeof(double), 1, file_S_new); - fwrite(reverse_data, sizeof(double), length, file_S_new); - fclose(file_S_new); - } - if (file_F != NULL) { - float *data_F = (float *)malloc(N * sizeof(float)); - - fread(data_F, sizeof(float), N, file_F); - fclose(file_F); - - for (int i = 0; i < M; i++) { - forward_data[i] = (double)data_F[drop + i]; - } - free(data_F); - - double mean_F = mean(M, forward_data); - double squaredMean_F = squared_mean(M, forward_data); - double moment2_F = central_moment(M, forward_data, mean_F, 2); - double moment4_F = central_moment(M, forward_data, mean_F, 4); - - compute_OO(M, forward_plan, forward_data, reverse_plan, reverse_data); - - sprintf(filename_F, "wolff_%lu_F_OO.dat", id); - FILE *file_F_new = fopen(filename_F, "wb"); - fwrite(&M_f, sizeof(double), 1, file_F_new); - fwrite(&mean_F, sizeof(double), 1, file_F_new); - fwrite(&squaredMean_F, sizeof(double), 1, file_F_new); - fwrite(&moment2_F, sizeof(double), 1, file_F_new); - fwrite(&moment4_F, sizeof(double), 1, file_F_new); - fwrite(reverse_data, sizeof(double), length, file_F_new); - fclose(file_F_new); - } - if (file_E != NULL) { - float *data_E = (float *)malloc(N * sizeof(float)); - - fread(data_E, sizeof(float), N, file_E); - fclose(file_E); - - for (int i = 0; i < M; i++) { - forward_data[i] = (double)data_E[drop + i]; - } - free(data_E); - - double mean_E = mean(M, forward_data); - double squaredMean_E = squared_mean(M, forward_data); - double moment2_E = central_moment(M, forward_data, mean_E, 2); - double moment4_E = central_moment(M, forward_data, mean_E, 4); - - compute_OO(M, forward_plan, forward_data, reverse_plan, reverse_data); - - sprintf(filename_E, "wolff_%lu_E_OO.dat", id); - FILE *file_E_new = fopen(filename_E, "wb"); - fwrite(&M_f, sizeof(double), 1, file_E_new); - fwrite(&mean_E, sizeof(double), 1, file_E_new); - fwrite(&squaredMean_E, sizeof(double), 1, file_E_new); - fwrite(&moment2_E, sizeof(double), 1, file_E_new); - fwrite(&moment4_E, sizeof(double), 1, file_E_new); - fwrite(reverse_data, sizeof(double), length, file_E_new); - fclose(file_E_new); - } - if (file_M != NULL) { - if (0 == strcmp(model, "PLANAR")) { - float *data_M = (float *)malloc(2 * N * sizeof(float)); - fread(data_M, sizeof(float), 2 * N, file_M); - fclose(file_M); - for (int i = 0; i < M; i++) { - forward_data[i] = (double)sqrt(pow(data_M[2 * drop + 2 * i], 2) + pow(data_M[2 * drop + 2 * i + 1], 2)); - } - free(data_M); - } else if (0 == strcmp(model, "HEISENBERG")) { - float *data_M = (float *)malloc(3 * N * sizeof(float)); - fread(data_M, sizeof(float), 3 * N, file_M); - fclose(file_M); - for (int i = 0; i < M; i++) { - forward_data[i] = sqrt(pow(data_M[3 * drop + 3 * i], 2) + pow(data_M[3 * drop + 3 * i + 1], 2) + pow(data_M[3 * drop + 3 * i + 2], 2)); - } - free(data_M); - } else if (0 == strcmp(model, "ISING")) { - int *data_M = (int *)malloc(N * sizeof(float)); - fread(data_M, sizeof(int), N, file_M); - fclose(file_M); - for (int i = 0; i < M; i++) { - forward_data[i] = (double)data_M[i]; - } - free(data_M); - } else { - printf("UNKNOWN MODEL\n"); - exit(EXIT_FAILURE); - } - - double mean_M = mean(M, forward_data); - double squaredMean_M = squared_mean(M, forward_data); - double moment2_M = central_moment(M, forward_data, mean_M, 2); - double moment4_M = central_moment(M, forward_data, mean_M, 4); - - compute_OO(M, forward_plan, forward_data, reverse_plan, reverse_data); - - sprintf(filename_M, "wolff_%lu_M_OO.dat", id); - FILE *file_M_new = fopen(filename_M, "wb"); - fwrite(&M_f, sizeof(double), 1, file_M_new); - fwrite(&mean_M, sizeof(double), 1, file_M_new); - fwrite(&squaredMean_M, sizeof(double), 1, file_M_new); - fwrite(&moment2_M, sizeof(double), 1, file_M_new); - fwrite(&moment4_M, sizeof(double), 1, file_M_new); - fwrite(reverse_data, sizeof(double), length, file_M_new); - fclose(file_M_new); - } - - printf("\033[F%lu: Correlation functions for %d steps written.\n", id, M); - fftw_destroy_plan(forward_plan); - fftw_destroy_plan(reverse_plan); - fftw_free(forward_data); - fftw_free(reverse_data); - - } - free(filename_E); - free(filename_S); - free(filename_F); - free(filename_M); - } - } - - free(model); - fclose(metadata); - fftw_cleanup(); - - return 0; -} - diff --git a/lib/include/wolff.hpp b/lib/include/wolff.hpp index b730c8d..b78cd4b 100644 --- a/lib/include/wolff.hpp +++ b/lib/include/wolff.hpp @@ -1,30 +1,27 @@ +#ifndef WOLFF_H +#define WOLFF_H + #include "wolff/cluster.hpp" -#include "wolff/state.hpp" template <class R_t, class X_t> -void wolff(count_t N, state_t <R_t, X_t>& s, std::function <R_t(std::mt19937&, X_t)> gen_R, wolff_measurement<R_t, X_t>& m, std::mt19937& r) { - -#ifdef FINITE_STATES -#ifdef NOFIELD - initialize_probs(s.J, s.T); -#else - initialize_probs(s.J, s.H, s.T); -#endif -#endif +void wolff(N_t N, wolff_system<R_t, X_t>& S, + std::function <R_t(std::mt19937&, X_t)> r_gen, + wolff_measurement<R_t, X_t>& A, std::mt19937& rng) { - std::uniform_int_distribution<v_t> dist(0, s.nv); + std::uniform_int_distribution<v_t> dist(0, S.nv - 1); - for (count_t steps = 0; steps < N; steps++) { - v_t v0 = dist(r); - R_t step = gen_R(r, s.spins[v0]); + for (N_t n = 0; n < N; n++) { + v_t i0 = dist(rng); + R_t r = r_gen(rng, S.s[i0]); - m.pre_cluster(s, steps, N, v0, step); + A.pre_cluster(n, N, S, i0, r); - flip_cluster<R_t, X_t>(s, v0, step, r, m); + wolff_cluster_flip<R_t, X_t>(S, i0, r, rng, A); - m.post_cluster(s, steps, N); + A.post_cluster(n, N, S); } - } +#endif + diff --git a/lib/include/wolff/cluster.hpp b/lib/include/wolff/cluster.hpp index 805e2c3..055cdf3 100644 --- a/lib/include/wolff/cluster.hpp +++ b/lib/include/wolff/cluster.hpp @@ -1,120 +1,122 @@ -#pragma once +#ifndef WOLFF_CLUSTER_H +#define WOLFF_CLUSTER_H #include <random> #include <cmath> #include <vector> -#include <stack> +#include <queue> #include "types.h" -#include "state.hpp" +#include "system.hpp" #include "graph.hpp" -#include "meas.h" +#include "measurement.hpp" template <class R_t, class X_t> -void flip_cluster(state_t<R_t, X_t>& s, v_t v0, const R_t& r, std::mt19937& rand, wolff_measurement<R_t, X_t>& m) { +void wolff_cluster_flip(wolff_system<R_t, X_t>& S, v_t i0, const R_t& r, + std::mt19937& rng, wolff_measurement<R_t, X_t>& A) { std::uniform_real_distribution<double> dist(0.0, 1.0); - std::stack<v_t> stack; - stack.push(v0); + std::queue<v_t> queue; + queue.push(i0); - std::vector<bool> marks(s.g.nv, false); + std::vector<bool> marks(S.G.nv, false); - while (!stack.empty()) { - v_t v = stack.top(); - stack.pop(); + while (!queue.empty()) { + v_t i = queue.front(); + queue.pop(); - if (!marks[v]) { // don't reprocess anyone we've already visited! - marks[v] = true; + if (!marks[i]) { // don't reprocess anyone we've already visited! + marks[i] = true; X_t si_new; -#ifndef NOFIELD - R_t R_new; +#ifndef WOLFF_NO_FIELD + R_t s0_new; - bool v_is_ghost = (v == s.nv); // ghost site has the last index + bool we_are_ghost = (i == S.nv); - if (v_is_ghost) { - R_new = r.act(s.R); // if we are, then we're moving the transformation + if (we_are_ghost) { + s0_new = r.act(S.s0); } else #endif { - si_new = r.act(s.spins[v]); // otherwise, we're moving the spin at our site + si_new = r.act(S.s[i]); } - for (const v_t &vn : s.g.v_adj[v]) { - double dE, prob; + for (const v_t &j : S.G.adj[i]) { + double dE, p; -#ifndef NOFIELD - bool vn_is_ghost = (vn == s.nv); // any of our neighbors could be the ghost +#ifndef WOLFF_NO_FIELD + bool neighbor_is_ghost = (j == S.nv); - if (v_is_ghost || vn_is_ghost) { // this is a ghost-involved bond - X_t rs_old, rs_new; + if (we_are_ghost || neighbor_is_ghost) { + X_t s0s_old, s0s_new; v_t non_ghost; - if (vn_is_ghost) { - // if our neighbor is the ghost, the current site is a normal - // spin - rotate it back! - rs_old = s.R.act_inverse(s.spins[v]); - rs_new = s.R.act_inverse(si_new); - non_ghost = v; + if (neighbor_is_ghost) { + non_ghost = i; + s0s_old = S.s0.act_inverse(S.s[i]); + s0s_new = S.s0.act_inverse(si_new); } else { - /* if we're the ghost, we need to rotate our neighbor back in - both the old and new ways */ - rs_old = s.R.act_inverse(s.spins[vn]); - rs_new = R_new.act_inverse(s.spins[vn]); - non_ghost = vn; + non_ghost = j; + s0s_old = S.s0.act_inverse(S.s[j]); + s0s_new = s0_new.act_inverse(S.s[j]); } -#ifdef SITE_DEPENDENCE - dE = s.H(non_ghost, rs_old) - s.H(non_ghost, rs_new); +#ifdef WOLFF_SITE_DEPENDENCE + dE = S.B(non_ghost, s0s_old) - S.B(non_ghost, s0s_new); #else - dE = s.H(rs_old) - s.H(rs_new); + dE = S.B(s0s_old) - S.B(s0s_new); #endif -#ifdef FINITE_STATES - prob = H_probs[state_to_ind(rs_old)][state_to_ind(rs_new)]; +#ifdef WOLFF_FINITE_STATES + p = finite_states_Bp[finite_states_enum(s0s_old)] + [finite_states_enum(s0s_new)]; #endif // run measurement hooks for encountering a ghost bond - m.ghost_bond_added(non_ghost, rs_old, rs_new, dE); + A.ghost_bond_visited(S, non_ghost, s0s_old, s0s_new, dE); } else // this is a perfectly normal bond! #endif { -#ifdef BOND_DEPENDENCE - dE = s.J(v, s.spins[v], vn, s.spins[vn]) - s.J(v, si_new, vn, s.spins[vn]); +#ifdef WOLFF_BOND_DEPENDENCE + dE = S.Z(i, S.s[i], j, S.s[j]) - S.Z(i, si_new, j, S.s[j]); #else - dE = s.J(s.spins[v], s.spins[vn]) - s.J(si_new, s.spins[vn]); + dE = S.Z(S.s[i], S.s[j]) - S.Z(si_new, S.s[j]); #endif - -#ifdef FINITE_STATES - prob = J_probs[state_to_ind(s.spins[v])][state_to_ind(si_new)][state_to_ind(s.spins[vn])]; +#ifdef WOLFF_FINITE_STATES + p = finite_states_Zp[finite_states_enum(S.s[i])] + [finite_states_enum(si_new)] + [finite_states_enum(S.s[j])]; #endif // run measurement hooks for encountering a plain bond - m.plain_bond_added(v, s.spins[v], si_new, vn, s.spins[vn], dE); + A.plain_bond_visited(S, i, si_new, j, dE); } #ifndef FINITE_STATES - prob = 1.0 - exp(-dE / s.T); + p = 1.0 - exp(-dE / S.T); #endif - if (dist(rand) < prob) { - stack.push(vn); // push the neighboring vertex to the stack + if (dist(rng) < p) { + queue.push(j); // push the neighboring vertex to the queue } } -#ifndef NOFIELD - if (v_is_ghost) { - m.ghost_site_transformed(s.R, R_new); - s.R = R_new; +#ifndef WOLFF_NO_FIELD + if (we_are_ghost) { + A.ghost_site_transformed(S, s0_new); + S.s0 = s0_new; } else #endif { - m.plain_site_transformed(v, s.spins[v], si_new); - s.spins[v] = si_new; + A.plain_site_transformed(S, i, si_new); + S.s[i] = si_new; } } } } +#endif + diff --git a/lib/include/wolff/finite_states.hpp b/lib/include/wolff/finite_states.hpp index 426edad..4cca69e 100644 --- a/lib/include/wolff/finite_states.hpp +++ b/lib/include/wolff/finite_states.hpp @@ -1,40 +1,35 @@ -#pragma once + +#ifndef WOLFF_FINITE_STATES +#define WOLFF_FINITE_STATES #include <cmath> -#include <functional> #include <array> -#define FINITE_STATES - -// must have N_STATES, states[N_STATES], and state_to_ind defined before -// invoking header +#include "system.hpp" -std::array<std::array<std::array<double, N_STATES>, N_STATES>, N_STATES> J_probs; -#ifndef NOFIELD -std::array<std::array<double, N_STATES>, N_STATES> H_probs; +std::array<std::array<std::array<double, WOLFF_FINITE_STATES_N>, WOLFF_FINITE_STATES_N>, WOLFF_FINITE_STATES_N> finite_states_Zp; +#ifndef WOLFF_NO_FIELD +std::array<std::array<double, WOLFF_FINITE_STATES_N>, WOLFF_FINITE_STATES_N> finite_states_Bp; #endif -template <class X_t> -#ifndef NOFIELD -void initialize_probs(std::function <double(X_t, X_t)> J, std::function <double(X_t)> H, double T) { - for (q_t i = 0; i < N_STATES; i++) { - for (q_t j = 0; j < N_STATES; j++) { - H_probs[i][j] = 1.0 - exp(-(H(states[i]) - H(states[j])) / T); +template <class R_t, class X_t> +void finite_states_init(const wolff_system<R_t, X_t>& S) { +#ifndef WOLFF_NO_FIELD + for (q_t i = 0; i < WOLFF_FINITE_STATES_N; i++) { + for (q_t j = 0; j < WOLFF_FINITE_STATES_N; j++) { + finite_states_Bp[i][j] = 1.0 - exp(-(S.B(finite_states_possible[i]) - S.B(finite_states_possible[j])) / S.T); } } -#else -void initialize_probs(std::function <double(X_t, X_t)> J, double T) { #endif - for (q_t i = 0; i < N_STATES; i++) { - for (q_t j = 0; j < N_STATES; j++) { - for (q_t k = 0; k < N_STATES; k++) { - J_probs[i][j][k] = 1.0 - exp(-(J(states[i], states[k]) - J(states[j], states[k])) / T); + for (q_t i = 0; i < WOLFF_FINITE_STATES_N; i++) { + for (q_t j = 0; j < WOLFF_FINITE_STATES_N; j++) { + for (q_t k = 0; k < WOLFF_FINITE_STATES_N; k++) { + finite_states_Zp[i][j][k] = 1.0 - exp(-(S.Z(finite_states_possible[i], finite_states_possible[k]) - S.Z(finite_states_possible[j], finite_states_possible[k])) / S.T); } } } } - - +#endif diff --git a/lib/include/wolff/graph.hpp b/lib/include/wolff/graph.hpp index 0aeb6af..fcd73fa 100644 --- a/lib/include/wolff/graph.hpp +++ b/lib/include/wolff/graph.hpp @@ -1,5 +1,6 @@ -#pragma once +#ifndef WOLFF_GRAPH_H +#define WOLFF_GRAPH_H #include <cmath> #include <vector> @@ -15,10 +16,12 @@ class graph_t { public: v_t ne; v_t nv; - std::vector<std::vector<v_t>> v_adj; + std::vector<std::vector<v_t>> adj; std::vector<std::vector<double>> coordinate; graph_t(D_t D, L_t L, lattice_t lat = SQUARE_LATTICE); void add_ext(); }; +#endif + diff --git a/lib/include/wolff/meas.h b/lib/include/wolff/meas.h deleted file mode 100644 index 4895eac..0000000 --- a/lib/include/wolff/meas.h +++ /dev/null @@ -1,19 +0,0 @@ - -#pragma once - -#include "types.h" - -template <class R_t, class X_t> -class wolff_measurement { - public: - virtual void pre_cluster(const state_t<R_t, X_t>&, count_t, count_t, v_t, const R_t&) = 0; - - virtual void plain_bond_added(v_t, const X_t&, const X_t&, v_t, const X_t&, double) = 0; - virtual void ghost_bond_added(v_t, const X_t&, const X_t&, double) = 0; - - virtual void plain_site_transformed(v_t, const X_t&, const X_t&) = 0; - virtual void ghost_site_transformed(const R_t&, const R_t&) = 0; - - virtual void post_cluster(const state_t<R_t, X_t>&, count_t, count_t) = 0; -}; - diff --git a/lib/include/wolff/measurement.hpp b/lib/include/wolff/measurement.hpp new file mode 100644 index 0000000..a6a5f79 --- /dev/null +++ b/lib/include/wolff/measurement.hpp @@ -0,0 +1,24 @@ + +#ifndef WOLFF_MEASUREMENTS +#define WOLFF_MEASUREMENTS + +#include "system.hpp" + +template <class R_t, class X_t> +class wolff_measurement { + public: + virtual void pre_cluster(N_t, N_t, const wolff_system<R_t, X_t>&, v_t, const R_t&) = 0; + + virtual void plain_bond_visited(const wolff_system<R_t, X_t>&, v_t, const X_t&, v_t, double) = 0; + virtual void plain_site_transformed(const wolff_system<R_t, X_t>&, v_t, const X_t&) = 0; + +#ifndef WOLFF_NO_FIELD + virtual void ghost_bond_visited(const wolff_system<R_t, X_t>&, v_t, const X_t&, const X_t&, double) = 0; + virtual void ghost_site_transformed(const wolff_system<R_t, X_t>&, const R_t&) = 0; +#endif + + virtual void post_cluster(N_t, N_t, const wolff_system<R_t, X_t>&) = 0; +}; + +#endif + diff --git a/examples/src/models/potts/dihedral.hpp b/lib/include/wolff/models/dihedral.hpp index cbc5687..cbc5687 100644 --- a/examples/src/models/potts/dihedral.hpp +++ b/lib/include/wolff/models/dihedral.hpp diff --git a/examples/src/models/roughening/dihedral_inf.hpp b/lib/include/wolff/models/dihedral_inf.hpp index 19fa195..bded387 100644 --- a/examples/src/models/roughening/dihedral_inf.hpp +++ b/lib/include/wolff/models/dihedral_inf.hpp @@ -1,5 +1,5 @@ -#include <wolff/types.h> +#include "../types.h" #include <cmath> #include "height.hpp" diff --git a/lib/include/wolff/models/height.hpp b/lib/include/wolff/models/height.hpp new file mode 100644 index 0000000..bd0ceb6 --- /dev/null +++ b/lib/include/wolff/models/height.hpp @@ -0,0 +1,43 @@ + +#pragma once + +#include <cmath> +#include <wolff/types.h> + +template <class T> +struct height_t { + T x; + + height_t() : x(0) {} + height_t(T x) : x(x) {} + + typedef T M_t; + typedef double F_t; + + inline T operator*(v_t a) const { + return x * a; + } + + inline double operator*(double a) const { + return x * a; + } + + inline T operator-(const height_t& h) const { + return x - h.x; + } +}; + +template <class T> +inline T& operator+=(T& M, const height_t<T> &h) { + M += h.x; + + return M; +} + +template <class T> +inline T& operator-=(T& M, const height_t<T> &h) { + M -= h.x; + + return M; +} + diff --git a/lib/include/wolff/models/ising.hpp b/lib/include/wolff/models/ising.hpp new file mode 100644 index 0000000..c6a3a47 --- /dev/null +++ b/lib/include/wolff/models/ising.hpp @@ -0,0 +1,81 @@ + +#ifndef WOLFF_MODELS_ISING +#define WOLFF_MODELS_ISING + +#include "../types.h" + +class ising_t { + public: + bool x; + + ising_t() : x(false) {} + + ising_t(bool x) : x(x) {} + ising_t(int x) : x((bool)x) {} + + ising_t act(const ising_t& s) const { + if (x) { + return ising_t(!s.x); + } else { + return ising_t(s.x); + } + } + + ising_t act_inverse(const ising_t& s) const { + return this->act(s); + } + + typedef int M_t; + typedef double F_t; + + inline M_t operator*(v_t a) const { + if (x) { + return -(M_t)a; + } else { + return (M_t)a; + } + } + + inline F_t operator*(double a) const { + if (x) { + return -a; + } else { + return a; + } + } + + inline M_t operator-(const ising_t &s) const { + if (x == s.x) { + return 0; + } else { + if (x) { + return -2; + } else { + return 2; + } + } + } + + inline int operator*(const ising_t& s) const { + if (x == s.x) { + return 1; + } else { + return -1; + } + } +}; + +inline ising_t::M_t operator*(v_t a, const ising_t& s) { + return s * a; +} + +inline ising_t::F_t operator*(double a, const ising_t& s) { + return s * a; +} + +#define WOLFF_FINITE_STATES_N 2 +const ising_t finite_states_possible[2] = {ising_t(0), ising_t(1)}; +q_t finite_states_enum(ising_t state) { return (q_t)state.x; } + +#endif + diff --git a/examples/src/models/On/orthogonal.hpp b/lib/include/wolff/models/orthogonal.hpp index f13357f..9dd5ddd 100644 --- a/examples/src/models/On/orthogonal.hpp +++ b/lib/include/wolff/models/orthogonal.hpp @@ -1,11 +1,9 @@ #pragma once -#include <stdlib.h> #include <random> #include <cmath> -#include <wolff/state.hpp> #include <wolff/types.h> #include "vector.hpp" @@ -114,7 +112,6 @@ class orthogonal_t : public std::array<std::array<T, q>, q> { }; - template <q_t q> orthogonal_t <q, double> generate_rotation_uniform (std::mt19937& r, const vector_t <q, double>& v) { std::normal_distribution<double> dist(0.0,1.0); diff --git a/examples/src/models/potts/potts.hpp b/lib/include/wolff/models/potts.hpp index f4765e2..903f25f 100644 --- a/examples/src/models/potts/potts.hpp +++ b/lib/include/wolff/models/potts.hpp @@ -1,22 +1,22 @@ + #pragma once #include <cmath> -#include <stdio.h> -#include <wolff/types.h> -#include "../On/vector.hpp" +#include "../types.h" +#include "vector.hpp" template <q_t q> class potts_t { public: q_t x; - typedef vector_t<q, int> M_t; - typedef vector_t<q, double> F_t; - potts_t() : x(0) {} potts_t(q_t x) : x(x) {} + typedef vector_t<q, int> M_t; + typedef vector_t<q, double> F_t; + inline vector_t<q, int> operator*(v_t a) const { vector_t<q, int> result; result.fill(0); @@ -44,29 +44,7 @@ class potts_t { } }; -// we could inherit norm_squared from vector.h, but convention dictates that -// potts norms be changed by a constant factor -template <q_t q> -double norm_squared(vector_t<q, double> s) { - double total = 0; - for (double& x : s) { - total += pow(x, 2); - } - - return total * (double)q / ((double)q - 1.0); -} - -// we could inherit write_magnetization from vector.h, but since M.x must sum -// to nv we don't need to write the last element -template <q_t q> -void write_magnetization(vector_t<q, int> M, FILE *outfile) { - for (int& x : M) { - fwrite(&x, sizeof(int), q - 1, outfile); - } -} - -// knock yourself out const potts_t<POTTSQ> states[256] = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {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}, {138}, {139}, {140}, {141}, {142}, {143}, {144}, {145}, {146}, {147}, {148}, {149}, {150}, {151}, {152}, {153}, {154}, {155}, {156}, {157}, {158}, {159}, {160}, {161}, {162}, {163}, {164}, {165}, {166}, {167}, {168}, {169}, {170}, {171}, {172}, {173}, {174}, {175}, {176}, {177}, {178}, {179}, {180}, {181}, {182}, {183}, {184}, {185}, {186}, {187}, {188}, {189}, {190}, {191}, {192}, {193}, {194}, {195}, {196}, {197}, {198}, {199}, {200}, {201}, {202}, {203}, {204}, {205}, {206}, {207}, {208}, {209}, {210}, {211}, {212}, {213}, {214}, {215}, {216}, {217}, {218}, {219}, {220}, {221}, {222}, {223}, {224}, {225}, {226}, {227}, {228}, {229}, {230}, {231}, {232}, {233}, {234}, {235}, {236}, {237}, {238}, {239}, {240}, {241}, {242}, {243}, {244}, {245}, {246}, {247}, {248}, {249}, {250}, {251}, {252}, {253}, {254}, {255}}; template <q_t q> -q_t state_to_ind(potts_t<q> state) { return (q_t)state.x; } +q_t finite_states_enum(potts_t<q> state) { return (q_t)state.x; } diff --git a/examples/src/models/potts/symmetric.hpp b/lib/include/wolff/models/symmetric.hpp index bc8673f..7bcc9a6 100644 --- a/examples/src/models/potts/symmetric.hpp +++ b/lib/include/wolff/models/symmetric.hpp @@ -1,9 +1,9 @@ #pragma once -#include <stdlib.h> #include <array> -#include <wolff/types.h> + +#include "../types.h" #include "potts.hpp" template <q_t q> @@ -36,7 +36,6 @@ class symmetric_t : public std::array<q_t, q> { } } - printf("Your spin wasn't a valid state!", s.x); exit(EXIT_FAILURE); } diff --git a/examples/src/models/On/vector.hpp b/lib/include/wolff/models/vector.hpp index 1cdb60a..1d635c8 100644 --- a/examples/src/models/On/vector.hpp +++ b/lib/include/wolff/models/vector.hpp @@ -1,9 +1,9 @@ #pragma once -#include <stdlib.h> #include <cmath> #include <array> +#include <iostream> #include <wolff/types.h> @@ -11,15 +11,9 @@ template <q_t q, class T> class vector_t : public std::array<T, q> { public: - // M_t needs to hold the sum of nv spins - typedef vector_t <q, T> M_t; - - // F_t needs to hold the double-weighted sum of spins - typedef vector_t <q, double> F_t; - vector_t() { this->fill((T)0); - (*this)[1] = (T)1; + (*this)[0] = (T)1; } vector_t(const T *x) { @@ -28,10 +22,13 @@ class vector_t : public std::array<T, q> { } } + typedef vector_t <q, T> M_t; + typedef vector_t <q, double> F_t; + template <class U> inline vector_t<q, T>& operator+=(const vector_t<q, U> &v) { for (q_t i = 0; i < q; i++) { - (*this)[i] += (U)v[i]; + (*this)[i] += (T)v[i]; } return *this; } @@ -39,7 +36,7 @@ class vector_t : public std::array<T, q> { template <class U> inline vector_t<q, T>& operator-=(const vector_t<q, U> &v) { for (q_t i = 0; i < q; i++) { - (*this)[i] -= (U)v[i]; + (*this)[i] -= (T)v[i]; } return *this; } @@ -67,52 +64,45 @@ class vector_t : public std::array<T, q> { diff -= v; return diff; } -}; + inline T operator*(const vector_t<q, T>& v) const { + double prod = 0; -template<q_t q, class T> -double norm_squared(vector_t<q, T> v) { - double tmp = 0; - for (T &x : v) { - tmp += pow(x, 2); - } + for (q_t i = 0; i < q; i++) { + prod += v[i] * (*this)[i]; + } - return tmp; -} + return prod; + } -template <q_t q, class T> -void write_magnetization(vector_t <q, T> M, FILE *outfile) { - for (q_t i = 0; i < q; i++) { - fwrite(&(M[i]), sizeof(T), q, outfile); - } -} + template <class U> + inline vector_t<q, T> operator/(U a) const { + vector_t<q, T> result; + for (q_t i = 0; i < q; i++) { + result[i] = (*this)[i] / a; + } -// below functions and definitions are unnecessary for wolff.h but useful. + return result; + } +}; -template <q_t q> // save some space and don't write whole doubles -void write_magnetization(vector_t <q, double> M, FILE *outfile) { - for (q_t i = 0; i < q; i++) { - float M_tmp = (float)M[i]; - fwrite(&M_tmp, sizeof(float), 1, outfile); - } +template<q_t q, class T> +inline vector_t<q, T> operator*(v_t a, const vector_t<q, T>&v) { + return v * a; } -template <q_t q, class T> -T dot(const vector_t <q, T>& v1, const vector_t <q, T>& v2) { - T prod = 0; - - for (q_t i = 0; i < q; i++) { - prod += v1[i] * v2[i]; - } - - return prod; +template<q_t q, class T> +inline vector_t<q, double> operator*(double a, const vector_t<q, T>&v) { + return v * a; } -template <q_t q, class T> -double H_vector(const vector_t <q, T>& v1, T *H) { - vector_t <q, T> H_vec(H); - return (double)(dot <q, T> (v1, H_vec)); +template<q_t q, class T> +std::ostream& operator<<(std::ostream& os, const vector_t<q, T>&v) { + os << "( "; + for (T vi : v) { + os << vi << " "; + } + os << ")"; + return os; } -char const *ON_strings[] = {"TRIVIAL", "ISING", "PLANAR", "HEISENBERG"}; - diff --git a/lib/include/wolff/state.hpp b/lib/include/wolff/state.hpp deleted file mode 100644 index 4909881..0000000 --- a/lib/include/wolff/state.hpp +++ /dev/null @@ -1,68 +0,0 @@ - -#pragma once - -#include <functional> -#include <vector> - -#include "types.h" -#include "graph.hpp" - -template <class R_t, class X_t> -class state_t { - public: - D_t D; // the dimension of the system - L_t L; // the linear size of the lattice - v_t nv; // the number of vertices in the original lattice - v_t ne; // the number of edges in the original lattice - graph_t g; // the graph defining the lattice with 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 - -#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 - , lattice_t lat = SQUARE_LATTICE) : D(D), L(L), g(D, L, lat), T(T), -#ifndef NOFIELD - R(), -#endif - J(J) -#ifndef NOFIELD - , H(H) -#endif - { - nv = g.nv; - ne = g.ne; - spins.resize(nv); -#ifndef NOFIELD - g.add_ext(); -#endif - } -}; - diff --git a/lib/include/wolff/system.hpp b/lib/include/wolff/system.hpp new file mode 100644 index 0000000..ac82f44 --- /dev/null +++ b/lib/include/wolff/system.hpp @@ -0,0 +1,70 @@ + +#ifndef WOLFF_STATE_H +#define WOLFF_STATE_H + +#include <functional> +#include <vector> + +#include "types.h" +#include "graph.hpp" + +template <class R_t, class X_t> +class wolff_system { + public: + D_t D; // dimension + L_t L; // linear size + v_t nv; // number of vertices + v_t ne; // number of edges + graph_t G; // the graph defining the lattice with ghost + double T; // the temperature + std::vector<X_t> s; // the state of the ordinary spins +#ifndef WOLFF_NO_FIELD + R_t s0; // the current state of the ghost site +#endif + +#ifdef WOLFF_BOND_DEPENDENCE + std::function <double(v_t, const X_t&, v_t, const X_t&)> Z; // coupling between sites +#else + std::function <double(const X_t&, const X_t&)> Z; // coupling between sites +#endif + +#ifndef WOLFF_NO_FIELD +#ifdef WOLFF_SITE_DEPENDENCE + std::function <double(v_t, const X_t&)> B; // coupling with the external field +#else + std::function <double(const X_t&)> B; // coupling with the external field +#endif +#endif + + wolff_system(D_t D, L_t L, double T, +#ifdef WOLFF_BOND_DEPENDENCE + std::function <double(v_t, const X_t&, v_t, const X_t&)> Z +#else + std::function <double(const X_t&, const X_t&)> Z +#endif +#ifndef WOLFF_NO_FIELD +#ifdef WOLFF_SITE_DEPENDENCE + , std::function <double(v_t, const X_t&)> B +#else + , std::function <double(const X_t&)> B +#endif +#endif + , lattice_t lat = SQUARE_LATTICE) : D(D), L(L), G(D, L, lat), T(T), Z(Z) +#ifndef WOLFF_NO_FIELD + , s0(), B(B) +#endif + { + nv = G.nv; + ne = G.ne; + s.resize(nv); +#ifndef WOLFF_NO_FIELD + G.add_ext(); +#endif +#ifdef WOLFF_FINITE_STATES + finite_states_init(*this); +#endif + } +}; + +#endif + diff --git a/lib/include/wolff/types.h b/lib/include/wolff/types.h index ec9efaf..68bd09e 100644 --- a/lib/include/wolff/types.h +++ b/lib/include/wolff/types.h @@ -1,36 +1,27 @@ #include <inttypes.h> -typedef uint_fast32_t v_t; -typedef uint_fast8_t q_t; -typedef uint_fast16_t R_t; -typedef uint_fast8_t D_t; -typedef uint_fast16_t L_t; -typedef uint_fast64_t count_t; -typedef int_fast64_t h_t; +typedef uint_fast32_t v_t; // vertex and edge indices +typedef uint_fast8_t q_t; // enumerated states +typedef uint_fast8_t D_t; // dimension +typedef uint_fast16_t L_t; // linear size +typedef uint_fast64_t N_t; // cycle iterator #define MAX_v UINT_FAST32_MAX #define MAX_Q UINT_FAST8_MAX -#define MAX_R UINT_FAST16_MAX #define MAX_D UINT_FAST8_MAX #define MAX_L UINT_FAST16_MAX -#define MAX_COUNT UINT_FAST64_MAX -#define MAX_H INT_FAST64_MAX -#define MIN_H INT_FAST64_MIN +#define MAX_N UINT_FAST64_MAX #define PRIv PRIuFAST32 #define PRIq PRIuFAST8 -#define PRIR PRIuFAST16 #define PRID PRIuFAST8 #define PRIL PRIuFAST16 -#define PRIcount PRIuFAST64 -#define PRIh PRIdFAST64 +#define PRIN PRIuFAST64 #define SCNv SCNuFAST32 #define SCNq SCNuFAST8 -#define SCNR SCNuFAST16 #define SCND SCNuFAST8 #define SCNL SCNuFAST16 -#define SCNcount SCNuFAST64 -#define SCNh SCNdFAST64 +#define SCNN SCNuFAST64 diff --git a/lib/src/graph.cpp b/lib/src/graph.cpp index c6f0ba6..b42aa78 100644 --- a/lib/src/graph.cpp +++ b/lib/src/graph.cpp @@ -7,11 +7,11 @@ graph_t::graph_t(D_t D, L_t L, lattice_t lat) { nv = pow(L, D); ne = D * nv; - v_adj.resize(nv); + adj.resize(nv); coordinate.resize(nv); - for (std::vector<v_t> v_adj_i : v_adj) { - v_adj_i.reserve(2 * D); + for (std::vector<v_t> adj_i : adj) { + adj_i.reserve(2 * D); } for (v_t i = 0; i < nv; i++) { @@ -19,21 +19,21 @@ graph_t::graph_t(D_t D, L_t L, lattice_t lat) { for (D_t j = 0; j < D; j++) { coordinate[i][j] = (i / (v_t)pow(L, D - j - 1)) % L; - v_adj[i].push_back(pow(L, j + 1) * (i / ((v_t)pow(L, j + 1))) + fmod(i + pow(L, j), pow(L, j + 1))); - v_adj[i].push_back(pow(L, j + 1) * (i / ((v_t)pow(L, j + 1))) + fmod(pow(L, j+1) + i - pow(L, j), pow(L, j + 1))); + adj[i].push_back(pow(L, j + 1) * (i / ((v_t)pow(L, j + 1))) + fmod(i + pow(L, j), pow(L, j + 1))); + adj[i].push_back(pow(L, j + 1) * (i / ((v_t)pow(L, j + 1))) + fmod(pow(L, j+1) + i - pow(L, j), pow(L, j + 1))); } } break; } case DIAGONAL_LATTICE: { nv = D * pow(L, D); - ne = D * nv; + ne = 2 * nv; - v_adj.resize(nv); + adj.resize(nv); coordinate.resize(nv); - for (std::vector<v_t> v_adj_i : v_adj) { - v_adj_i.reserve(4 * (D - 1)); + for (std::vector<v_t> adj_i : adj) { + adj_i.reserve(4 * (D - 1)); } for (D_t i = 0; i < D; i++) { @@ -42,10 +42,10 @@ graph_t::graph_t(D_t D, L_t L, lattice_t lat) { for (v_t j = 0; j < pow(L, D); j++) { v_t vc = sb + j; - v_adj[vc].push_back(((i + 1) % D) * pow(L, D) + j); - v_adj[vc].push_back(((i + 1) % D) * pow(L, D) + pow(L, D - 1) * (j / (v_t)pow(L, D - 1)) + (j + 1 - 2 * (i % 2)) % L); - v_adj[vc].push_back(((i + 1) % D) * pow(L, D) + pow(L, D - 1) * ((L + (j/ (v_t)pow(L, D - 1)) - 1 + 2 * (i % 2)) % L) + (j - i) % L); - v_adj[vc].push_back(((i + 1) % D) * pow(L, D) + pow(L, D - 1) * ((L + (j/ (v_t)pow(L, D - 1)) - 1 + 2 * (i % 2)) % L) + (j + 1 - i) % L); + adj[vc].push_back(((i + 1) % D) * pow(L, D) + j); + adj[vc].push_back(((i + 1) % D) * pow(L, D) + pow(L, D - 1) * (j / (v_t)pow(L, D - 1)) + (j + 1 - 2 * (i % 2)) % L); + adj[vc].push_back(((i + 1) % D) * pow(L, D) + pow(L, D - 1) * ((L + (j/ (v_t)pow(L, D - 1)) - 1 + 2 * (i % 2)) % L) + (j - i) % L); + adj[vc].push_back(((i + 1) % D) * pow(L, D) + pow(L, D - 1) * ((L + (j/ (v_t)pow(L, D - 1)) - 1 + 2 * (i % 2)) % L) + (j + 1 - i) % L); } } break; @@ -54,16 +54,16 @@ graph_t::graph_t(D_t D, L_t L, lattice_t lat) { } void graph_t::add_ext() { - for (std::vector<v_t>& v_adj_i : v_adj) { - v_adj_i.push_back(nv); + for (std::vector<v_t>& adj_i : adj) { + adj_i.push_back(nv); } - v_adj.resize(nv + 1); + adj.resize(nv + 1); coordinate.resize(nv + 1); - v_adj[nv].reserve(nv); + adj[nv].reserve(nv); for (v_t i = 0; i < nv; i++) { - v_adj[nv].push_back(i); + adj[nv].push_back(i); } coordinate[nv].resize(coordinate[0].size()); |