mc.cpp 5.53 KB
Newer Older
1
#include "mc.h"
2
3
namespace loadl {

Lukas Weber's avatar
wrong &    
Lukas Weber committed
4
mc::mc(const parser &p) : param{p} {
5
6
	therm_ = p.get<int>("thermalization");
	pt_sweeps_per_global_update_ = p.get<int>("pt_sweeps_per_global_update", -1);
7
8
}

9
void mc::write_output(const std::string &) {}
10

11
double mc::random01() {
Lukas Weber's avatar
Lukas Weber committed
12
	return rng->random_double();
13
}
Lukas Weber's avatar
Lukas Weber committed
14

15
int mc::sweep() const {
16
	return sweep_;
Lukas Weber's avatar
Lukas Weber committed
17
}
18

19
void mc::_init() {
20
21
22
	// simple profiling support: measure the time spent for sweeps/measurements etc
	measure.add_observable("_ll_checkpoint_read_time", 1);
	measure.add_observable("_ll_checkpoint_write_time", 1);
23
24
	measure.add_observable("_ll_measurement_time", pt_mode_ ? pt_sweeps_per_global_update_ : 1000);
	measure.add_observable("_ll_sweep_time", pt_mode_ ? pt_sweeps_per_global_update_ : 1000);
25

26
27
28
29
	if(pt_mode_) {
		if(param.get<bool>("pt_statistics", false)) {
			measure.add_observable("_ll_pt_rank", 1);
		}
30
	}
Lukas Weber's avatar
Lukas Weber committed
31

32
33
34
35
36
	if(param.defined("seed")) {
		rng.reset(new random_number_generator(param.get<uint64_t>("seed")));
	} else {
		rng.reset(new random_number_generator());
	}
Lukas Weber's avatar
Lukas Weber committed
37

38
	init();
39
40
}

41
void mc::_do_measurement() {
42
43
44
45
46
47
	struct timespec tstart, tend;
	clock_gettime(CLOCK_MONOTONIC_RAW, &tstart);

	do_measurement();

	clock_gettime(CLOCK_MONOTONIC_RAW, &tend);
48
49
50

	double measurement_time =
	    (tend.tv_sec - tstart.tv_sec) + 1e-9 * (tend.tv_nsec - tstart.tv_nsec);
51
52
53
54
	measure.add("_ll_measurement_time", measurement_time);
	if(measurement_time > max_meas_time_) {
		max_meas_time_ = measurement_time;
	}
55
56
}

57
void mc::_do_update() {
58
59
	struct timespec tstart, tend;
	clock_gettime(CLOCK_MONOTONIC_RAW, &tstart);
60
	sweep_++;
61

62
	do_update();
63
	clock_gettime(CLOCK_MONOTONIC_RAW, &tend);
64
65
66
67
68
69

	double sweep_time = (tend.tv_sec - tstart.tv_sec) + 1e-9 * (tend.tv_nsec - tstart.tv_nsec);
	measure.add("_ll_sweep_time", sweep_time);
	if(sweep_time > max_sweep_time_) {
		max_sweep_time_ = sweep_time;
	}
70
71
}

72
void mc::_pt_update_param(const std::string& param_name, double new_param, const std::string &new_dir) {
73
	// take over the bins of the new target dir
74
	{
Lukas Weber's avatar
Lukas Weber committed
75
		iodump dump_file = iodump::open_readonly(new_dir + ".dump.h5");
76
		measure.checkpoint_read(dump_file.get_root().open_group("measurements"));
77
	}
78

79
80
	auto unclean = measure.is_unclean();
	if(unclean) {
Lukas Weber's avatar
Lukas Weber committed
81
82
83
84
85
86
		throw std::runtime_error(
		    fmt::format("Unclean observable: {}\nIn parallel tempering mode you have to choose the "
		                "binsize for all observables so that it is commensurate with "
		                "pt_sweeps_per_global_update (so that all bins are empty once it happens). "
		                "If you don’t like this limitation, implement it properly.",
		                *unclean));
87
88
	}

89
	pt_update_param(param_name, new_param);
90
91
92
}

void mc::pt_measure_statistics() {
93
94
95
96
97
	if(param.get<bool>("pt_statistics", false)) {
		int rank;
		MPI_Comm_rank(MPI_COMM_WORLD, &rank);
		measure.add("_ll_pt_rank", rank);
	}
98
99
}

100
101
double mc::_pt_weight_ratio(const std::string& param_name, double new_param) {
	double wr = pt_weight_ratio(param_name, new_param);
Lukas Weber's avatar
Lukas Weber committed
102
103
104
	return wr;
}

105
void mc::measurements_write(const std::string &dir) {
106
107
108
	// blocks limit scopes of the dump file handles to ensure they are closed at the right time.
	{
		iodump meas_file = iodump::open_readwrite(dir + ".meas.h5");
109
110
		auto g = meas_file.get_root();
		measure.samples_write(g);
111
	}
112
113
114
115
116
117
118
}

void mc::_write(const std::string &dir) {
	struct timespec tstart, tend;
	clock_gettime(CLOCK_MONOTONIC_RAW, &tstart);

	measurements_write(dir);
119

120
121
122
	{
		iodump dump_file = iodump::create(dir + ".dump.h5.tmp");
		auto g = dump_file.get_root();
123

124
125
		rng->checkpoint_write(g.open_group("random_number_generator"));
		checkpoint_write(g.open_group("simulation"));
126
		measure.checkpoint_write(g.open_group("measurements"));
127

128
129
130
131
		g.write("max_checkpoint_write_time", max_checkpoint_write_time_);
		g.write("max_sweep_time", max_sweep_time_);
		g.write("max_meas_time", max_meas_time_);

132
133
134
135
		g.write("sweeps", sweep_);
		g.write("thermalization_sweeps", std::min(therm_, sweep_)); // only for convenience
	}
	rename((dir + ".dump.h5.tmp").c_str(), (dir + ".dump.h5").c_str());
136

137
	clock_gettime(CLOCK_MONOTONIC_RAW, &tend);
138
139
	double checkpoint_write_time =
	    (tend.tv_sec - tstart.tv_sec) + 1e-9 * (tend.tv_nsec - tstart.tv_nsec);
140
141
142
143
144
145
146
147
	measure.add("_ll_checkpoint_write_time", checkpoint_write_time);
	if(checkpoint_write_time > max_checkpoint_write_time_) {
		max_checkpoint_write_time_ = checkpoint_write_time;
	}
}

double mc::safe_exit_interval() {
	// this is more or less guesswork in an attempt to make it safe for as many cases as possible
148
	return 2 * (max_checkpoint_write_time_ + max_sweep_time_ + max_meas_time_) + 2;
149
150
}

151
bool mc::_read(const std::string &dir) {
Lukas Weber's avatar
Lukas Weber committed
152
	if(!file_exists(dir + ".dump.h5")) {
153
154
		return false;
	}
155
156
157
158
159
160

	struct timespec tstart, tend;
	clock_gettime(CLOCK_MONOTONIC_RAW, &tstart);

	iodump dump_file = iodump::open_readonly(dir + ".dump.h5");
	auto g = dump_file.get_root();
Lukas Weber's avatar
Lukas Weber committed
161
162

	rng.reset(new random_number_generator());
163
	rng->checkpoint_read(g.open_group("random_number_generator"));
Lukas Weber's avatar
Lukas Weber committed
164
	measure.checkpoint_read(g.open_group("measurements"));
165
166
167
168
	checkpoint_read(g.open_group("simulation"));

	g.read("sweeps", sweep_);

169
170
171
172
	g.read("max_checkpoint_write_time", max_checkpoint_write_time_);
	g.read("max_sweep_time", max_sweep_time_);
	g.read("max_meas_time", max_meas_time_);

173
174
175
	clock_gettime(CLOCK_MONOTONIC_RAW, &tend);
	measure.add("_ll_checkpoint_read_time",
	            (tend.tv_sec - tstart.tv_sec) + 1e-9 * (tend.tv_nsec - tstart.tv_nsec));
176
177
178
	return true;
}

179
void mc::_write_output(const std::string &filename) {
180
	write_output(filename);
181
182
}

183
bool mc::is_thermalized() {
184
185
186
187
	int sweep = sweep_;
	if(pt_mode_ && pt_sweeps_per_global_update_ > 0) {
		sweep /= pt_sweeps_per_global_update_;
	}
Lukas Weber's avatar
Lukas Weber committed
188

189
	return sweep >= therm_;
190
}
191
}