HILA
Loading...
Searching...
No Matches
mmain.cpp
1////////////////////////////////////////////////////////////////////////////////
2/// @author Jaakko Hällfors
3////////////////////////////////////////////////////////////////////////////////
4#include <stdio.h>
5#include <stdlib.h>
6#include <time.h>
7#include <random>
8
9#include "hila.h"
10#include "multicanonical.h"
11
12static_assert(NDIM == 3, "NDIM must be 3 here");
13
14Field<double> compute_local_action(Field<double> phi);
15void multican_update(Field<double> &phi);
16double order_parameter(Field<double> &phi);
17void iterate_weights(Field<double> &phi);
18
19// For the action we take a simple real scalar field with a
20// potential with two degenerate minima.
21Field<double> compute_local_action(Field<double> phi) {
22 Field<double> action;
23 onsites(ALL) {
24 action[X] = -pow(phi[X], 2) + pow(phi[X], 4);
25 }
26 foralldir(d) onsites(ALL) {
27 action[X] += pow(phi[X] - phi[X - d], 2);
28 action[X] += pow(phi[X + d] - phi[X], 2);
29 }
30 return action;
31}
32
33// Construct some kind of update algorithm. Here we have a standard
34// Metropolis-Hastings algorithm that creates a proposal field for the
35// final multicanonical acceptance in the end.
36void multican_update(Field<double> &phi, Parity PAR) {
37 // Get a temporary field
38 Field<double> new_phi = phi;
39
40 // Get a field of random numbers
41 Field<double> delta = 0;
42 onsites(PAR) hila::gaussian_random(delta[X]);
43
44 // Add change to temporary field
45 new_phi += 0.5 * delta;
46
47 // Get the local differences in actions
48 auto old_action = compute_local_action(phi);
49 auto new_action = compute_local_action(new_phi);
50 onsites(PAR) {
51 // compute log(exp(- delta S))
52 double log_P = -(new_action[X] - old_action[X]);
53 // Get a random uniform from [0,1] and reject based on that
54 double log_rand = log(hila::random());
55 if (log_rand > log_P) {
56 new_phi[X] = phi[X];
57 }
58 }
59
60 double OP_old = order_parameter(phi);
61 double OP_new = order_parameter(new_phi);
62
63 // Use the multicanonical accept_reject for a final update decision
64 if (hila::muca::accept_reject(OP_old, OP_new)) {
65 phi = new_phi;
66 }
67}
68
69// Mean value of phi is a convenient order parameter, since its cheap
70// to compute and has different values in the different minima.
71double order_parameter(Field<double> &phi) {
72 double OP = phi.sum();
73 return OP / lattice.volume();
74}
75
76// The weight iteration consists of a simple loop
77// where muca::iterate_weights is being fed with measurements
78// of the order parameter. The status informs us when the iteration
79// algorithm thinks its done and kills the loop. We save the weight data
80// for good measure.
81void iterate_weights(Field<double> &phi) {
82 bool iterate_status = true;
83 while (iterate_status) {
84 // Perform a number of updates
85 for (int i = 0; i < 25; i++) {
86 multican_update(phi, ODD);
87 multican_update(phi, EVEN);
88 }
89 // compute and feed the order parameter of the configuration to the
90 // iterator
91 double OP = order_parameter(phi);
92 iterate_status = hila::muca::iterate_weights(OP);
93 }
94 hila::muca::write_weight_function(hila::muca::generate_outfile_name());
95}
96
97void multi_iterate_weights(std::vector<Field<double>> &N_phi) {
98 bool iterate_status = true;
99 std::vector<double> OPs(N_phi.size());
100 while (iterate_status) {
101 // Perform a number of updates
102 for (int j = 0; j < N_phi.size(); j++) {
103 for (int i = 0; i < 50; i++) {
104 multican_update(N_phi[j], ODD);
105 multican_update(N_phi[j], EVEN);
106 }
107 OPs[j] = order_parameter(N_phi[j]);
108 }
109
110 // compute and feed the order parameter of the configuration to the
111 // iterator
112 iterate_status = hila::muca::iterate_weights(OPs[0]);
113 }
114 hila::muca::write_weight_function(hila::muca::generate_outfile_name());
115}
116
117// Here we combine the above functions into a full simulation that
118// iterates the weights as well as performs a run of measurements
119// on the order parameter using the iterated (or loaded) weight function.
120// Check the order parameter histograms to see the effect!
121int main(int argc, char *argv[]) {
122 hila::cmdline.add_flag("-muca", "If used, multicanonical methods are applied.");
123 hila::initialize(argc, argv);
124 hila::cmdline.print_help();
125 // hila::finishrun();
126
127 lattice.setup({12, 12, 12});
129
130 hila::muca::initialise("muca_parameters");
131
132 // Initialise a field
133 Field<double> phi = 0;
134
135 // Open a file for measurements
136 bool muca = hila::cmdline.flag_present("-muca");
137 std::ofstream MFile;
138 if (muca) {
139 hila::out0 << "Running a multicanonical simulation.\n";
140 MFile.open("muca_measurements", std::ios_base::app);
141 } else {
142 hila::out0 << "Running a standard simulation.\n";
143 MFile.open("ca_measurements", std::ios_base::app);
144 }
145
146 if (muca)
147 iterate_weights(phi);
148
149 const int N = 10000;
150 // Get some measurements
151 for (int i = 1; i <= N; i++) {
152 double OP = order_parameter(phi);
153 char buffer[1024];
154 // Remember that you need the weight of each measured configuration
155 // for the post-processing!
156 sprintf(buffer, "%d\t%e\t%e\n", i, OP, hila::muca::weight(OP));
157 if (hila::myrank() == 0)
158 MFile << std::string(buffer);
159
160 if (i % (N / 100) == 0)
161 hila::out0 << 100 * i / N << "% done\n";
162 // Perform a set of updates
163 for (int i = 0; i < 50; i++) {
164 multican_update(phi, ODD);
165 multican_update(phi, EVEN);
166 }
167 }
168
169 MFile.close();
171}
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...