135 std::ifstream stream(file_path);
137 throw std::runtime_error(
"cannot open neighbour list file: " + file_path);
139 std::vector<std::string> lines;
141 while (std::getline(stream, line)) {
142 std::string trimmed = trim(line);
143 if (!trimmed.empty()) {
144 lines.push_back(trimmed);
149 data.
real_lattice = read_lattice_block(file_path, lines,
"real_lattice");
152 std::vector<std::string> kpoint_body = extract_block(file_path, lines,
"kpoints");
153 if (kpoint_body.empty()) {
154 throw std::runtime_error(file_path +
": 'kpoints' block is empty");
156 int declared_count = 0;
158 std::istringstream count_stream(kpoint_body[0]);
159 if (!(count_stream >> declared_count) || declared_count <= 0) {
160 throw std::runtime_error(file_path +
161 ": 'kpoints' block must open with a positive count");
164 if (
static_cast<int>(kpoint_body.size()) - 1 != declared_count) {
165 throw std::runtime_error(file_path +
": 'kpoints' block declares " +
166 std::to_string(declared_count) +
" k-points but holds " +
167 std::to_string(kpoint_body.size() - 1) +
" rows");
169 data.
kpoints.reserve(declared_count);
170 for (
int index = 0; index < declared_count; index++) {
171 std::istringstream row_stream(kpoint_body[index + 1]);
173 if (!(row_stream >> kpoint.
x >> kpoint.
y >> kpoint.
z)) {
174 throw std::runtime_error(file_path +
175 ": malformed k-point row: " + kpoint_body[index + 1]);
177 data.
kpoints.push_back(kpoint);
183 std::ifstream stream(file_path);
185 throw std::runtime_error(
"cannot open overlap file: " + file_path);
187 std::string comment_line;
188 std::getline(stream, comment_line);
193 throw std::runtime_error(file_path +
194 ": missing or malformed 'num_bands num_kpts nntot' header");
210 const long long block_element_count =
212 for (
int kpoint_index = 0; kpoint_index < data.
number_of_kpoints; kpoint_index++) {
215 int block_kpoint = 0;
216 int neighbor_kpoint = 0;
218 if (!(stream >> block_kpoint >> neighbor_kpoint >> shift.
x >> shift.
y >> shift.
z)) {
219 throw std::runtime_error(
220 file_path +
": file ended before the declared " +
223 " (k,b) blocks were read");
231 if (block_kpoint != kpoint_index + 1) {
232 throw std::runtime_error(
233 file_path +
": blocks must sweep k-points in order; expected k-point " +
234 std::to_string(kpoint_index + 1) +
", found " +
235 std::to_string(block_kpoint));
237 data.
neighbors[kpoint_index][neighbor_index].neighbor_kpoint_index = to_zero_based(
239 data.
neighbors[kpoint_index][neighbor_index].periodic_image_shift = shift;
241 std::vector<Complex>& block = data.
overlaps[kpoint_index][neighbor_index];
242 block.resize(block_element_count);
248 for (
int element_index = 0; element_index < block_element_count; element_index++) {
249 Real real_part = 0.0;
250 Real imaginary_part = 0.0;
251 if (!(stream >> real_part >> imaginary_part)) {
252 throw std::runtime_error(file_path +
253 ": file ended inside a (k,b) overlap block");
255 block[element_index] =
Complex(real_part, imaginary_part);
263 std::ifstream stream(file_path);
265 throw std::runtime_error(
"cannot open projection file: " + file_path);
267 std::string comment_line;
268 std::getline(stream, comment_line);
273 throw std::runtime_error(file_path +
274 ": missing or malformed 'num_bands num_kpts num_wann' header");
285 const std::size_t block_size =
295 std::vector<bool>(block_size,
false));
297 const long long total_elements =
static_cast<long long>(data.
number_of_bands) *
299 for (
long long element_index = 0; element_index < total_elements; element_index++) {
303 Real real_part = 0.0;
304 Real imaginary_part = 0.0;
305 if (!(stream >> band >> wannier >> kpoint >> real_part >> imaginary_part)) {
306 throw std::runtime_error(file_path +
": file ended before the declared " +
307 std::to_string(total_elements) +
308 " projection elements were read");
310 int band_index = to_zero_based(file_path,
"band", band, data.
number_of_bands);
313 int kpoint_index = to_zero_based(file_path,
"k-point", kpoint, data.
number_of_kpoints);
316 static_cast<std::size_t
>(wannier_index) * data.
number_of_bands + band_index;
317 if (written[kpoint_index][slot]) {
318 throw std::runtime_error(
319 file_path +
": duplicate projection entry for band " + std::to_string(band) +
320 ", Wannier " + std::to_string(wannier) +
", k-point " + std::to_string(kpoint));
323 written[kpoint_index][slot] =
true;
334 std::ifstream stream(file_path);
336 throw std::runtime_error(
"cannot open eigenvalue file: " + file_path);
344 std::vector<Entry> entries;
345 int maximum_band = 0;
346 int maximum_kpoint = 0;
349 while (std::getline(stream, line)) {
350 std::istringstream line_stream(line);
352 if (!(line_stream >> entry.band >> entry.kpoint >> entry.value)) {
353 if (line.find_first_not_of(
" \t\r\n") == std::string::npos) {
356 throw std::runtime_error(file_path +
357 ": expected 'band kpoint eigenvalue', got: " + line);
366 std::string trailing;
367 if (line_stream >> trailing) {
368 throw std::runtime_error(
369 file_path +
": unexpected '" + trailing +
370 "' after the eigenvalue (Fortran D exponents are not a valid .eig "
371 "notation; this reader accepts E exponents and plain decimals): " +
374 if (entry.band < 1 || entry.kpoint < 1) {
375 throw std::runtime_error(
376 file_path +
": band and k-point indices are 1-based, got band " +
377 std::to_string(entry.band) +
", k-point " + std::to_string(entry.kpoint));
379 maximum_band = std::max(maximum_band, entry.band);
380 maximum_kpoint = std::max(maximum_kpoint, entry.kpoint);
381 entries.push_back(entry);
383 if (entries.empty()) {
384 throw std::runtime_error(file_path +
": contains no eigenvalue lines");
393 if (
static_cast<long long>(maximum_band) * maximum_kpoint !=
394 static_cast<long long>(entries.size())) {
395 throw std::runtime_error(
396 file_path +
": " + std::to_string(entries.size()) +
397 " eigenvalue lines cannot fill a " + std::to_string(maximum_kpoint) +
398 " k-point by " + std::to_string(maximum_band) +
399 " band table (the largest indices seen); the file is truncated or an index is "
406 std::vector<std::vector<bool>> written(maximum_kpoint,
407 std::vector<bool>(maximum_band,
false));
408 for (
const Entry& entry : entries) {
409 if (written[entry.kpoint - 1][entry.band - 1]) {
410 throw std::runtime_error(file_path +
": duplicate eigenvalue for band " +
411 std::to_string(entry.band) +
", k-point " +
412 std::to_string(entry.kpoint));
416 written[entry.kpoint - 1][entry.band - 1] =
true;
418 for (
int kpoint_index = 0; kpoint_index < maximum_kpoint; kpoint_index++) {
419 for (
int band_index = 0; band_index < maximum_band; band_index++) {
420 if (!written[kpoint_index][band_index]) {
421 throw std::runtime_error(
422 file_path +
": index range implies " + std::to_string(maximum_kpoint) +
423 " k-points x " + std::to_string(maximum_band) +
424 " bands, but the entry for band " + std::to_string(band_index + 1) +
425 ", k-point " + std::to_string(kpoint_index + 1) +
" is absent");