HILA
Loading...
Searching...
No Matches
multicanonical_example.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2/// @file multicanonical_example.cpp
3/// @author Jaakko Hällfors
4/// @brief Example usage of the multicanonical tools
5/// @details Simple working method for using multicanonical update on a scalar field where
6/// the system exhibits critical freezing.
7////////////////////////////////////////////////////////////////////////////////
8#include <stdio.h>
9#include <stdlib.h>
10#include <time.h>
11#include <random>
12
13#include "hila.h"
14#include "multicanonical.h"
15
16static_assert(NDIM == 3, "NDIM must be 3 here");
17
18Field<double> compute_local_action(Field<double> phi);
19void multican_update(Field<double> &phi);
20double order_parameter(Field<double> &phi);
21void iterate_weights(Field<double> &phi);
22
23// For the action we take a simple real scalar field with a
24// potential with two degenerate minima.
25Field<double> compute_local_action(Field<double> phi) {
26 Field<double> action;
27 onsites(ALL) {
28 action[X] = -pow(phi[X], 2) + pow(phi[X], 4);
29 }
30 foralldir(d) onsites(ALL) {
31 action[X] += pow(phi[X] - phi[X - d], 2);
32 action[X] += pow(phi[X + d] - phi[X], 2);
33 }
34 return action;
35}
36
37// Construct some kind of update algorithm. Here we have a standard
38// Metropolis-Hastings algorithm that creates a proposal field for the
39// final multicanonical acceptance in the end.
40void multican_update(Field<double> &phi, Parity PAR) {
41 // Get a temporary field
42 Field<double> new_phi = phi;
43
44 // Get a field of random numbers
45 Field<double> delta = 0;
46 onsites(PAR) hila::gaussian_random(delta[X]);
47
48 // Add change to temporary field
49 new_phi += 0.5 * delta;
50
51 // Get the local differences in actions
52 auto old_action = compute_local_action(phi);
53 auto new_action = compute_local_action(new_phi);
54 onsites(PAR) {
55 // compute log(exp(- delta S))
56 double log_P = -(new_action[X] - old_action[X]);
57 // Get a random uniform from [0,1] and reject based on that
58 double log_rand = log(hila::random());
59 if (log_rand > log_P) {
60 new_phi[X] = phi[X];
61 }
62 }
63
64 double OP_old = order_parameter(phi);
65 double OP_new = order_parameter(new_phi);
66
67 // Use the multicanonical accept_reject for a final update decision
68 if (hila::muca::accept_reject(OP_old, OP_new)) {
69 phi = new_phi;
70 }
71}
72
73// Mean value of phi is a convenient order parameter, since its cheap
74// to compute and has different values in the different minima.
75double order_parameter(Field<double> &phi) {
76 double OP = phi.sum();
77 return OP / lattice.volume();
78}
79
80// The weight iteration consists of a simple loop
81// where muca::iterate_weights is being fed with measurements
82// of the order parameter. The status informs us when the iteration
83// algorithm thinks its done and kills the loop. We save the weight data
84// for good measure.
85void iterate_weights(Field<double> &phi) {
86 bool iterate_status = true;
87 while (iterate_status) {
88 // Perform a number of updates
89 for (int i = 0; i < 25; i++) {
90 multican_update(phi, ODD);
91 multican_update(phi, EVEN);
92 }
93 // compute and feed the order parameter of the configuration to the
94 // iterator
95 double OP = order_parameter(phi);
96 iterate_status = hila::muca::iterate_weights(OP);
97 }
98 hila::muca::write_weight_function(hila::muca::generate_outfile_name());
99}
100
101// Here we combine the above functions into a full simulation that
102// iterates the weights as well as performs a run of measurements
103// on the order parameter using the iterated (or loaded) weight function.
104// Check the order parameter histograms to see the effect!
105int main(int argc, char *argv[]) {
106 hila::cmdline.add_flag("-muca", "If used, multicanonical methods are applied.");
107 hila::initialize(argc, argv);
108 hila::cmdline.print_help();
109 // hila::finishrun();
110
111 lattice.setup({12, 12, 12});
113
114 hila::muca::initialise("muca_parameters");
115
116 // Initialise a field
117 Field<double> phi = 0;
118
119 // Open a file for measurements
120 bool muca = hila::cmdline.flag_present("-muca");
121 std::ofstream MFile;
122 if (muca) {
123 hila::out0 << "Running a multicanonical simulation.\n";
124 MFile.open("muca_measurements", std::ios_base::app);
125 } else {
126 hila::out0 << "Running a standard simulation.\n";
127 MFile.open("ca_measurements", std::ios_base::app);
128 }
129
130 if (muca)
131 iterate_weights(phi);
132
133 const int N = 10000;
134 // Get some measurements
135 for (int i = 1; i <= N; i++) {
136 double OP = order_parameter(phi);
137 char buffer[1024];
138 // Remember that you need the weight of each measured configuration
139 // for the post-processing!
140 sprintf(buffer, "%d\t%e\t%e\n", i, OP, hila::muca::weight(OP));
141 if (hila::myrank() == 0)
142 MFile << std::string(buffer);
143
144 if (i % (N / 100) == 0)
145 hila::out0 << 100 * i / N << "% done\n";
146 // Perform a set of updates
147 for (int i = 0; i < 50; i++) {
148 multican_update(phi, ODD);
149 multican_update(phi, EVEN);
150 }
151 }
152
153 MFile.close();
155}
Array< n, m, T > pow(Array< n, m, T > a, int b)
Power.
Definition array.h:1204
Array< n, m, T > log(Array< n, m, T > a)
Logarithm.
Definition array.h:1069
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
T sum(Parity par=Parity::all, bool allreduce=true) const
Sum reduction of Field.
Definition reduction.h:296
void setup(const CoordinateVector &siz)
General lattice setup.
Definition lattice.cpp:33
Parity
Parity enum with values EVEN, ODD, ALL; refers to parity of the site. Parity of site (x,...
constexpr Parity EVEN
bit pattern: 001
#define foralldir(d)
Macro to loop over (all) Direction(s)
Definition coordinates.h:78
constexpr Parity ODD
bit pattern: 010
constexpr Parity ALL
bit pattern: 011
void write_weight_function(string W_function_filename)
Reads the precomputed weight function from run_parameters struct and saves it into a file.
void initialise(const string wfile_name)
Loads parameters and weights for the multicanonical computation.
Header for model agnostic implementation of various multicanonical (muca) methods.
T gaussian_random()
Template function T hila::gaussian_random<T>(),generates gaussian random value of type T,...
Definition random.h:183
double random()
Real valued uniform random number generator.
Definition hila_gpu.cpp:121
int myrank()
rank of this node
Definition com_mpi.cpp:234
std::ostream out0
This writes output only from main process (node 0)
void initialize(int argc, char **argv)
Read in command line arguments. Initialise default stream and MPI communication.
void seed_random(uint64_t seed, bool device_rng=true)
Seed random generators with 64-bit unsigned value. On MPI shuffles the seed so that different MPI ran...
Definition random.cpp:86
void finishrun()
Normal, controlled exit - all nodes must call this. Prints timing information and information about c...