29 static constexpr uint32_t
MAGIC = 0x51334350;
32 bool save(
const std::string& filename,
34 bool save_wavefunctions =
false)
const override {
35 std::ofstream file_stream(filename, std::ios::binary);
36 if (!file_stream.is_open())
39 write_header(file_stream, snapshot, save_wavefunctions);
40 write_charge_density(file_stream, snapshot);
41 write_eigenvalues(file_stream, snapshot);
42 write_effective_potential(file_stream, snapshot);
43 write_one_center_occupations(file_stream, snapshot);
45 if (save_wavefunctions) {
46 const auto* planewave_snapshot =
48 if (planewave_snapshot) {
49 write_wavefunctions(file_stream, *planewave_snapshot);
53 return file_stream.good();
57 std::ifstream file_stream(filename, std::ios::binary);
58 if (!file_stream.is_open())
61 uint8_t has_wavefunctions = 0;
62 uint32_t file_version = 0;
63 if (!read_header(file_stream, snapshot, has_wavefunctions, file_version))
66 read_charge_density(file_stream, snapshot);
67 read_eigenvalues(file_stream, snapshot);
70 if (file_version >= 2) {
71 read_effective_potential(file_stream, snapshot);
74 if (file_version >= 3) {
75 read_one_center_occupations(file_stream, snapshot);
78 if (has_wavefunctions) {
79 auto* planewave_snapshot =
81 if (planewave_snapshot) {
82 read_wavefunctions(file_stream, *planewave_snapshot);
86 return file_stream.good();
90 template <
typename T>
static void write_value(std::ofstream& file_stream,
const T& value) {
91 file_stream.write(
reinterpret_cast<const char*
>(&value),
sizeof(T));
94 template <
typename T>
static void read_value(std::ifstream& file_stream, T& value) {
95 file_stream.read(
reinterpret_cast<char*
>(&value),
sizeof(T));
98 static void write_header(std::ofstream& file_stream,
99 const KohnShamQuantumSystemSnapshot& snapshot,
100 bool save_wavefunctions) {
101 write_value(file_stream,
MAGIC);
102 write_value(file_stream,
VERSION);
103 write_value(file_stream, snapshot.iteration);
104 write_value(file_stream, snapshot.number_of_spin_components);
105 write_value(file_stream, snapshot.number_of_bands);
106 write_value(file_stream, snapshot.number_of_kpoint_states);
107 write_value(file_stream, snapshot.total_energy);
108 write_value(file_stream, snapshot.converged);
109 uint8_t has_wavefunctions = save_wavefunctions ? 1 : 0;
110 write_value(file_stream, has_wavefunctions);
113 static void write_charge_density(std::ofstream& file_stream,
114 const KohnShamQuantumSystemSnapshot& snapshot) {
115 int number_of_spin_density_components =
116 static_cast<int>(snapshot.charge_density_real.size());
117 write_value(file_stream, number_of_spin_density_components);
118 for (
const auto& density_component : snapshot.charge_density_real) {
119 int number_of_grid_points =
static_cast<int>(density_component.size());
120 write_value(file_stream, number_of_grid_points);
121 file_stream.write(
reinterpret_cast<const char*
>(density_component.data()),
122 number_of_grid_points *
sizeof(
Real));
126 static void write_eigenvalues(std::ofstream& file_stream,
127 const KohnShamQuantumSystemSnapshot& snapshot) {
128 for (
size_t kpoint_state_index = 0; kpoint_state_index < snapshot.eigenvalues.rows();
129 kpoint_state_index++) {
130 int number_of_bands_column =
static_cast<int>(snapshot.eigenvalues.cols());
131 write_value(file_stream, number_of_bands_column);
133 reinterpret_cast<const char*
>(snapshot.eigenvalues[kpoint_state_index]),
134 number_of_bands_column *
sizeof(
Real));
138 static void write_wavefunctions(std::ofstream& file_stream,
139 const PlanewaveKohnShamQuantumSystemSnapshot& snapshot) {
140 for (
const auto& kpoint_bands : snapshot.wavefunction_coefficients) {
141 for (
const auto& band : kpoint_bands) {
142 int number_of_plane_waves =
static_cast<int>(band.size());
143 write_value(file_stream, number_of_plane_waves);
144 file_stream.write(
reinterpret_cast<const char*
>(band.data()),
145 number_of_plane_waves *
sizeof(
Complex));
150 static bool read_header(std::ifstream& file_stream,
151 KohnShamQuantumSystemSnapshot& snapshot,
152 uint8_t& has_wavefunctions,
153 uint32_t& file_version) {
155 read_value(file_stream, magic);
156 read_value(file_stream,
version);
161 read_value(file_stream, snapshot.iteration);
162 read_value(file_stream, snapshot.number_of_spin_components);
163 read_value(file_stream, snapshot.number_of_bands);
164 read_value(file_stream, snapshot.number_of_kpoint_states);
165 read_value(file_stream, snapshot.total_energy);
166 read_value(file_stream, snapshot.converged);
167 read_value(file_stream, has_wavefunctions);
171 static void read_charge_density(std::ifstream& file_stream,
172 KohnShamQuantumSystemSnapshot& snapshot) {
173 int number_of_spin_density_components;
174 read_value(file_stream, number_of_spin_density_components);
175 if (number_of_spin_density_components != snapshot.number_of_spin_components) {
177 "Checkpoint corrupt: header declares {} spin component(s) but charge density "
179 snapshot.number_of_spin_components,
180 number_of_spin_density_components);
181 file_stream.setstate(std::ios::failbit);
184 snapshot.charge_density_real.resize(number_of_spin_density_components);
185 for (
auto& density_component : snapshot.charge_density_real) {
186 int number_of_grid_points;
187 read_value(file_stream, number_of_grid_points);
188 density_component.resize(number_of_grid_points);
189 file_stream.read(
reinterpret_cast<char*
>(density_component.data()),
190 number_of_grid_points *
sizeof(
Real));
194 static void read_eigenvalues(std::ifstream& file_stream,
195 KohnShamQuantumSystemSnapshot& snapshot) {
196 snapshot.eigenvalues.resize(
197 snapshot.number_of_kpoint_states, snapshot.number_of_bands, 0.0);
198 for (
int kpoint_state_index = 0; kpoint_state_index < snapshot.number_of_kpoint_states;
199 kpoint_state_index++) {
200 int number_of_bands_column;
201 read_value(file_stream, number_of_bands_column);
202 if (number_of_bands_column != snapshot.number_of_bands) {
203 log::error(
"Checkpoint corrupt: header declares {} band(s) per k-point but "
204 "eigenvalue row {} has {}.",
205 snapshot.number_of_bands,
207 number_of_bands_column);
208 file_stream.setstate(std::ios::failbit);
211 file_stream.read(
reinterpret_cast<char*
>(snapshot.eigenvalues[kpoint_state_index]),
212 number_of_bands_column *
sizeof(
Real));
216 static void write_effective_potential(std::ofstream& file_stream,
217 const KohnShamQuantumSystemSnapshot& snapshot) {
218 int number_of_spin_components =
static_cast<int>(snapshot.effective_potential_real.size());
219 write_value(file_stream, number_of_spin_components);
220 for (
const auto& potential_component : snapshot.effective_potential_real) {
221 int number_of_grid_points =
static_cast<int>(potential_component.size());
222 write_value(file_stream, number_of_grid_points);
223 file_stream.write(
reinterpret_cast<const char*
>(potential_component.data()),
224 number_of_grid_points *
sizeof(
Real));
228 static void read_effective_potential(std::ifstream& file_stream,
229 KohnShamQuantumSystemSnapshot& snapshot) {
230 int number_of_spin_components;
231 read_value(file_stream, number_of_spin_components);
232 snapshot.effective_potential_real.resize(number_of_spin_components);
233 for (
auto& potential_component : snapshot.effective_potential_real) {
234 int number_of_grid_points;
235 read_value(file_stream, number_of_grid_points);
236 potential_component.resize(number_of_grid_points);
237 file_stream.read(
reinterpret_cast<char*
>(potential_component.data()),
238 number_of_grid_points *
sizeof(
Real));
242 static void write_one_center_occupations(std::ofstream& file_stream,
243 const KohnShamQuantumSystemSnapshot& snapshot) {
244 int number_of_spin_components =
static_cast<int>(snapshot.one_center_occupations.size());
245 write_value(file_stream, number_of_spin_components);
246 for (
const auto& occupations : snapshot.one_center_occupations) {
247 int number_of_atoms =
static_cast<int>(occupations.rows());
248 int row_length =
static_cast<int>(occupations.cols());
249 write_value(file_stream, number_of_atoms);
250 write_value(file_stream, row_length);
251 file_stream.write(
reinterpret_cast<const char*
>(occupations.raw().data()),
252 occupations.raw().size() *
sizeof(
Real));
256 static void read_one_center_occupations(std::ifstream& file_stream,
257 KohnShamQuantumSystemSnapshot& snapshot) {
258 int number_of_spin_components;
259 read_value(file_stream, number_of_spin_components);
260 if (!file_stream.good() || number_of_spin_components < 0 || number_of_spin_components > 2) {
261 log::error(
"Checkpoint corrupt: the on-site occupation section declares {} spin "
263 number_of_spin_components);
264 file_stream.setstate(std::ios::failbit);
267 snapshot.one_center_occupations.assign(number_of_spin_components, {});
268 for (
auto& occupations : snapshot.one_center_occupations) {
271 read_value(file_stream, number_of_atoms);
272 read_value(file_stream, row_length);
273 if (!file_stream.good() || number_of_atoms < 0 || row_length < 0) {
274 log::error(
"Checkpoint corrupt: on-site occupations declared as {} atom(s) by "
278 file_stream.setstate(std::ios::failbit);
281 occupations.assign(number_of_atoms, row_length, 0.0);
282 file_stream.read(
reinterpret_cast<char*
>(occupations.raw().data()),
283 occupations.raw().size() *
sizeof(
Real));
287 static void read_wavefunctions(std::ifstream& file_stream,
288 PlanewaveKohnShamQuantumSystemSnapshot& snapshot) {
289 snapshot.wavefunction_coefficients.resize(snapshot.number_of_kpoint_states);
290 for (
auto& kpoint_bands : snapshot.wavefunction_coefficients) {
291 kpoint_bands.resize(snapshot.number_of_bands);
292 for (
auto& band : kpoint_bands) {
293 int number_of_plane_waves;
294 read_value(file_stream, number_of_plane_waves);
295 band.resize(number_of_plane_waves);
296 file_stream.read(
reinterpret_cast<char*
>(band.data()),
297 number_of_plane_waves *
sizeof(
Complex));