15using string = std::string;
16using int_vector = std::vector<int>;
17using vector = std::vector<double>;
23typedef bool (* finish_condition_pointer)(std::vector<int> &visits);
169static vector g_OPValues(1,0);
170static vector g_OPBinLimits(2,0);
171static vector g_WValues(1,0);
172static int_vector g_N_OP_Bin(1,0);
173static int_vector g_N_OP_BinTotal(1,0);
174static int g_WeightIterationCount = 0;
175static bool g_WeightIterationFlag =
true;
183iteration_pointer iterate_weights;
186finish_condition_pointer finish_check;
199 sprintf(buffer, fmt.c_str(), input_value);
214 std::stringstream ss;
215 std::time_t t = std::time(
nullptr);
216 std::tm tm = *std::localtime(&t);
217 ss << std::put_time(&tm,
"created_%Y.%m.%d_%H:%M:%S");
218 string date = ss.str();
220 filename = filename + date;
237 string output_loc = par.
get(
"output file location");
238 string outfile_name_base = par.
get(
"output file name base");
240 string weight_loc = par.
get(
"weight file location");
241 string iter_method = par.
get(
"iteration method");
242 string hard_walls = par.
get(
"hard walls");
243 double max_OP = par.
get(
"max OP");
244 double min_OP = par.
get(
"min OP");
245 int bin_number = par.
get(
"bin number");
246 string iter_vis = par.
get(
"iteration visuals");
249 string finish_condition = par.
get(
"finish condition");
250 int DIM_sample_size = par.
get(
"DIM sample size");
251 int DIM_check_interval = par.
get(
"DIM visit check interval");
252 double add_initial = par.
get(
"add initial");
253 double add_minimum = par.
get(
"add minimum");
256 int CIM_sample_size = par.
get(
"CIM sample size");
257 int initial_bin_hits = par.
get(
"initial bin hits");
258 int OC_max_iter = par.
get(
"OC max iter");
259 int OC_frequency = par.
get(
"OC frequency");
281 bool AR_ITER =
false;
284 if (iter_vis.compare(
"YES") == 0)
286 else visuals =
false;
289 if (hard_walls.compare(
"YES") == 0)
331 hila::out0 <<
"\nLoading the user supplied weight function.\n";
336 int header_length = 1, data_length = -1;
337 std::ifstream W_file;
338 W_file.open(W_function_filename.c_str());
339 if (W_file.is_open())
342 while(std::getline(W_file, line))
344 if (std::regex_match(line, std::regex(
".*OP_value.*")))
354 W_file.open(W_function_filename.c_str());
357 int count = - header_length;
359 printf(
"Weight function has header length of %d rows.\n",
361 printf(
"Weight function has data length of %d rows.\n",
363 printf(
"Reading the weight function into the program.\n");
366 g_OPBinLimits = vector(data_length);
367 g_OPValues = vector(data_length - 1);
368 g_WValues = vector(data_length - 1);
372 if (W_file.is_open())
375 while (std::getline(W_file, line))
377 float bin_lim,
weight, centre;
379 if (count >= 0 and count < data_length - 1)
381 sscanf(line.c_str(),
"%e\t%e\t%e",
382 &bin_lim, ¢re, &
weight);
384 g_OPBinLimits[count] = bin_lim;
385 g_OPValues[count] = centre;
386 g_WValues[count] =
weight;
389 if (count == data_length - 1)
391 sscanf(line.c_str(),
"%e", &bin_lim);
392 g_OPBinLimits[count] = bin_lim;
401 for (
int i = 0; i < data_length - 1; i++)
403 g_OPValues[i] = (g_OPBinLimits[i + 1] + g_OPBinLimits[i]) / 2.0;
406 hila::out0 <<
"\nSuccesfully loaded the user provided weight function.\n";
424 std::ofstream W_file;
426 printf(
"Writing the current weight function into a file...\n");
427 W_file.open(W_function_filename.c_str());
430 to_file(W_file,
"%s",
"OP_bin_limit\tOP_value\tWeight\n");
432 for (i = 0; i < g_OPValues.size(); ++i)
434 to_file(W_file,
"%e\t", g_OPBinLimits[i]);
435 to_file(W_file,
"%e\t", g_OPValues[i]);
436 to_file(W_file,
"%e\n", g_WValues[i]);
439 to_file(W_file,
"%e\n", g_OPBinLimits[i]);
441 printf(
"Succesfully saved the weight function into file\n%s\n",
442 W_function_filename.c_str());
459 if (OP <= g_OPValues.front())
462 val = std::numeric_limits<double>::infinity();
464 val = g_WValues.front();
466 else if (OP >= g_OPValues.back())
469 val = std::numeric_limits<double>::infinity();
471 val = g_WValues.back();
477 auto it = std::lower_bound(g_OPValues.begin(),
478 g_OPValues.end(), OP);
479 int i = std::distance(g_OPValues.begin(), it) - 1;
480 double y_value = g_WValues[i + 1] - g_WValues[i];
481 double x_value = g_OPValues[i + 1] - g_OPValues[i];
482 double slope = y_value / x_value;
484 double xbase = g_OPValues[i];
485 double ybase = g_WValues[i];
487 double xdiff = OP - xbase;
488 val = ybase + xdiff * slope;
555 double log_P = - (W_new - W_old);
560 if (
::log(rval) < log_P)
598static int find_OP_bin_index(
double OP)
601 if (OP <= g_OPBinLimits.front())
605 else if (OP >= g_OPBinLimits.back())
610 auto it = std::lower_bound(g_OPBinLimits.begin(),
611 g_OPBinLimits.end(), OP);
612 int lower_limit = std::distance(g_OPBinLimits.begin(), it) - 1;
623static void bin_OP_value(
double OP)
626 if (OP <= g_OPBinLimits.front())
630 else if (OP >= g_OPBinLimits.back())
635 auto it = std::lower_bound(g_OPBinLimits.begin(),
636 g_OPBinLimits.end(), OP);
637 int lower_limit = std::distance(g_OPBinLimits.begin(), it) - 1;
638 g_N_OP_Bin[lower_limit] += 1;
649static bool all_visited(int_vector &n)
652 for (
int i = 0; i < len; ++i)
654 if (n[i] == 0)
return false;
666static bool first_last_visited(int_vector &n)
669 if ((n[0] == 0) or (n[len - 1] == 0))
690 finish_check = fc_pointer;
707static void overcorrect(vector &Weight, int_vector &n_sum)
709 int N = n_sum.size();
711 constexpr float C = 1;
713 for (
int m = 0; m < N; ++m)
715 if (n_sum[m] > 0) W[m] = C *
::log(n_sum[m]);
720 for (
int i = 0; i < N; ++i)
722 Weight[i] += W[i] - base;
737static void recursive_weight_iteration(vector &Weight, int_vector &n,
738 int_vector &g_sum, vector &g_log_h_sum)
745 for (
int m = 0; m < N; ++m)
749 log_h[m] =
::log(n[m]) + Weight[m];
760 for (
int m = 1; m < N; ++m)
764 if (n[m] > nmin and n[m - 1] > nmin)
766 gm = n[m] + n[m - 1];
771 g_log_h_sum[m] += gm * (log_h[m] - log_h[m - 1]);
773 W[m] = W[m - 1] + g_log_h_sum[m] / g_sum[m];
882static vector get_equidistant_bin_limits()
884 double min = g_WParam.
min_OP;
885 double max = g_WParam.
max_OP;
887 vector bin_edges(N + 1);
888 double diff = (max - min) / (N - 1);
889 for (
int i = 0; i < N + 1; ++i)
891 bin_edges[i] = min - diff / 2.0 + diff * i;
901static void setup_equidistant_bins()
905 g_OPBinLimits = get_equidistant_bin_limits();
906 for (
int i = 0; i < g_OPValues.size(); i++)
908 double centre = (g_OPBinLimits[i + 1] + g_OPBinLimits[i]) / 2.0;
909 g_OPValues[i] = centre;
919static void initialise_weight_vectors()
925 g_WValues = vector(N, 0.0);
926 g_OPValues = vector(N, 0.0);
927 g_OPBinLimits = vector(N + 1, 0.0);
929 setup_equidistant_bins();
931 g_N_OP_Bin = int_vector(N, 0);
932 g_N_OP_BinTotal = int_vector(N, 0);
940 int N = g_WValues.size();
941 g_N_OP_Bin = int_vector(N, 0);
942 g_N_OP_BinTotal = int_vector(N, 0);
954static bool iterate_weight_function_direct(
double OP)
956 bool continue_iteration;
960 int N = g_WValues.size();
963 g_WeightIterationCount += 1;
965 if (g_WeightIterationCount >= samples)
967 for (
int m = 0; m < N; m++)
969 g_WValues[m] += g_WParam.
DIP.
C * g_N_OP_Bin[m] * N / samples;
970 g_N_OP_BinTotal[m] += g_N_OP_Bin[m];
973 if (g_WParam.
visuals) print_iteration_histogram();
975 double base = *std::min_element(g_WValues.begin(), g_WValues.end());
976 for (
int m = 0; m < N; ++m)
980 g_WValues[m] -= base;
983 g_WeightIterationCount = 0;
985 if (finish_check(g_N_OP_BinTotal))
987 for (
int m = 0; m < N; m++)
989 g_N_OP_BinTotal[m] = 0;
992 g_WParam.
DIP.
C /= 1.5;
1000 continue_iteration =
true;
1003 hila::out0 <<
"Reached minimum update size.\n";
1004 hila::out0 <<
"Weight iteration complete.\n";
1005 continue_iteration =
false;
1009 return continue_iteration;
1024static bool iterate_weight_function_direct_single(
double OP)
1026 int continue_iteration;
1030 int N = g_WValues.size();
1032 int bin_index = find_OP_bin_index(OP);
1034 if (bin_index != -1)
1035 g_N_OP_BinTotal[bin_index] += 1;
1037 g_WeightIterationCount += 1;
1039 g_WValues[bin_index] += g_WParam.
DIP.
C;
1044 double base = *std::min_element(g_WValues.begin(), g_WValues.end());
1045 for (
int m = 0; m < N; ++m)
1049 g_WValues[m] -= base;
1054 if (g_WParam.
visuals) print_iteration_histogram();
1057 if (finish_check(g_N_OP_BinTotal))
1059 for (
int m = 0; m < N; m++)
1061 g_N_OP_BinTotal[m] = 0;
1064 g_WParam.
DIP.
C /= 1.5;
1066 hila::out0 <<
"New update size C = " << g_WParam.
DIP.
C <<
"\n\n";
1069 continue_iteration =
true;
1072 hila::out0 <<
"Reached minimum update size.\n";
1073 hila::out0 <<
"Weight iteration complete.\n";
1074 continue_iteration =
false;
1082 return continue_iteration;
1092static void print_iteration_histogram()
1095 int N = g_WValues.size();
1097 int nmax = *std::max_element(g_N_OP_Bin.begin(), g_N_OP_Bin.end());
1099 printf(
"Order Parameter Weight Number of hits\n");
1101 for (
int m = 0; m < N; ++m)
1106 std::string n_sum_hist =
"";
1107 if (g_N_OP_BinTotal[m] > 0) n_sum_hist +=
"O";
1108 for (
int i = 0; i < int(g_N_OP_Bin[m] * 200.0 / samples); i++)
1112 printf(
"%-20.3f%-20.3f%d\t\t\t%s\n", g_OPValues[m],
1113 g_WValues[m], g_N_OP_Bin[m], n_sum_hist.c_str());
1127static void setup_iteration()
1131 if (g_WParam.
method.compare(
"direct") == 0)
1135 iterate_weights = &iterate_weight_function_direct;
1139 iterate_weights = &iterate_weight_function_direct_single;
1145 iterate_weights = &iterate_weight_function_direct;
1150 g_WeightIterationCount = 0;
1155 finish_check = &all_visited;
1159 finish_check = &first_last_visited;
1163 finish_check = &all_visited;
1196 if (g_WParam.
weight_loc.compare(
"NONE") != 0)
1202 initialise_weight_vectors();
void set_continuous_iteration(bool YN)
Enable/disable continuous weight iteration.
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.
bool accept_reject(const double OP_old, const double OP_new)
Accepts/rejects a multicanonical update.
void to_file(std::ofstream &output_file, string fmt, K input_value)
Writes a variable to the file, given the format string.
void read_weight_function(string W_function_filename)
Reads a precomputed weight function from file.
void set_weight_iter_flag(bool YN)
Sets the static g_WeightIterationFlag to given boolean.
double weight_function(double OP)
Returns a weight associated to the used order parameter.
double weight(double OP)
process 0 interface to "weight function" for the user accessing the weights.
void read_weight_parameters(string parameter_file_name)
Parses the weight parameter file and fills the g_WParam struct.
bool check_weight_iter_flag()
Returns the value of the static g_WeightIterationFlag to user.
string generate_outfile_name()
Generates a time stamped and otherwise appropriate file name for the saved weight function files.
void set_direct_iteration_FC(bool(*fc_pointer)(int_vector &n))
Sets a user provided function to the check in the "direct iteration" method.
Header for model agnostic implementation of various multicanonical (muca) methods.
Implement hila::swap for gauge fields.
logger_class log
Now declare the logger.
double random()
Real valued uniform random number generator.
int myrank()
rank of this node
std::ostream out0
This writes output only from main process (node 0)
std::ofstream output_file
this is just a hook to store output file, if it is in use
T broadcast(T &var, int rank=0)
Broadcast the value of var to all MPI ranks from rank (default=0).
An internal struct parametrising the canonical weight iteration method.
int initial_bin_hits
Initial number of entries in the bin totals.
int sample_size
Number of samples before weight function update.
int OC_max_iter
Up to which iteration the overcorrection updates can be used.
int OC_frequency
How often the overcorrection update is used.
An internal struct parametrising the direct weight iteration method.
double C
Magnitude of the weight update.
int single_check_interval
Determines how often the update condition is checked for the case direct_iteration::sample_size = 1.
string finish_condition
Determines the iteration condition for the iteration method.
double C_min
Minimum magnitude of the weight update.
int sample_size
Number of samples before weight function update.
double C_init
Initial magnitude of the weight update.
An internal struct parametrising multicanonical methods.
string weight_loc
Path to the weight function file.
double min_OP
Minimum order parameter value.
double max_OP
Maximum order parameter value.
bool hard_walls
Whether the weight outside max_OP and min_OP is infinite.
string method
Name of the iteration method.
int bin_number
Number of OP bins.
struct canonical_iteration CIP
A substruct that contains method specific parameters.
struct direct_iteration DIP
A substruct that contains method specific parameters.
bool AR_iteration
Whether to update the weights after each call to accept_reject.
bool visuals
Whether to print histogram during iteration.
string outfile_name_base
Prefix for the saved weight function files.
void update(GaugeField< group > &U, const parameters &p, bool relax)
Wrapper update function.