TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
wannier_loader.cpp
1#include "./wannier_loader.hpp"
4
5#include <itertools/itertools.hpp>
6#include <nda/nda.hpp>
7
8#include <fstream> // std::ifstream
9#include <stdexcept>
10#include <utility>
11
12namespace triqs::experimental::lattice {
13
14 namespace detail {
15 template <typename T> T read(std::ifstream &file) {
16 T x;
17 file >> x;
18 return x;
19 }
20
21 // The generator is consumed eagerly in the same scope, so the file reference stays valid (and std::ifstream is
22 // non-copyable).
23 // NOLINTNEXTLINE(cppcoreguidelines-avoid-reference-coroutine-parameters)
24 template <typename T> generator<T> read_N(std::ifstream &file, int n) {
25 for ([[maybe_unused]] auto i : nda::range(n)) co_yield read<T>(file);
26 }
27 } // namespace detail
28
29 // ------------------------------------------------------
30
31 w90_tb_data_t read_wannier90_tb_data(std::string const &w90_path_and_seedname) {
32
33 // open the file
34 std::string tb_filename = w90_path_and_seedname + "_tb.dat";
35 std::ifstream file(tb_filename);
36 if (!file.is_open()) throw std::runtime_error("Could not open *_tb.dat file with provided name " + tb_filename);
37
38 // skip first line, it's a 5 item line of the date / time
39 for ([[maybe_unused]] auto i : detail::read_N<std::string>(file, 5)) {}
40
41 // read the lattice vectors
42 auto latt_vec = nda::matrix<double>(3, 3);
43 for (auto x : {0, 1, 2})
44 for (auto y : {0, 1, 2}) { latt_vec(x, y) = detail::read<double>(file); }
45
46 // next two lines have number of wannier centers, number of R vectors
47 int n_wannier = detail::read<int>(file);
48 int n_r = detail::read<int>(file);
49
50 // read in the R vector degeneracies
51 std::vector<int> r_degeneracies;
52 for (auto i : detail::read_N<int>(file, n_r)) { r_degeneracies.push_back(i); };
53
54 // set up containers for R and H_r
55 std::vector<std::array<long, 3>> r_vectors;
56 std::vector<nda::array<dcomplex, 2>> H_r;
57 std::vector<nda::array<dcomplex, 3>> position_op_r;
58
59 for ([[maybe_unused]] auto r : nda::range(n_r)) {
60 r_vectors.emplace_back(std::array<long, 3>{0, 0, 0});
61 H_r.emplace_back(n_wannier, n_wannier);
62 position_op_r.emplace_back(n_wannier, n_wannier, 3);
63 }
64
65 // read the R vectors and the Wannier Hamiltonian -------
66 std::array<long, 3> R{};
67 for (auto ir : nda::range(n_r)) {
68
69 file >> R[0] >> R[1] >> R[2];
70 for ([[maybe_unused]] auto [x, y] : product(nda::range(n_wannier), nda::range(n_wannier))) {
71
72 double re = 0.0, im = 0.0;
73 int ii = 0, jj = 0; // read these from the file rather than as loop indices
74 file >> ii >> jj >> re >> im;
75
76 // check state
77 // NB if we want to use ws_cells vec data, we will likely want to use all wannier indices instead
78 // (wannier90 indexes this from 1)
79 if ((ii == 1) and (jj == 1))
80 for (int i : {0, 1, 2}) r_vectors[ir][i] = R[i];
81
82 // merge degeneracy vector into Wannier Hamiltonian (note, W90 indexes from 1)
83 H_r[ir](ii - 1, jj - 1) = dcomplex{re, im} / r_degeneracies[ir];
84 }
85 }
86
87 // read in the position operator elements in the Wannier basis --------------------
88 // These appear at the end of the tb.dat file in units of Angstrom
89 for (auto ir : nda::range(n_r)) {
90 // R vector is listed before each r_matrix block in the file
91 file >> R[0] >> R[1] >> R[2];
92 for ([[maybe_unused]] auto [x, y] : product(nda::range(n_wannier), nda::range(n_wannier))) {
93
94 std::array<double, 3> re{}, im{};
95 int ii = 0, jj = 0; // read these from the file rather than as loop indices
96 file >> ii >> jj >> re[0] >> im[0] >> re[1] >> im[1] >> re[2] >> im[2];
97 // merge degeneracy information into the position operator
98 for (auto idx_cart : {0, 1, 2})
99 position_op_r[ir](ii - 1, jj - 1, idx_cart) = dcomplex{re[idx_cart], im[idx_cart]} / r_degeneracies[ir]; // in Angstrom
100 }
101 }
102 return {std::move(r_vectors), std::move(H_r), std::move(position_op_r), std::move(latt_vec)};
103 }
104
105 w90_hr_data_t read_wannier90_hr_data(std::string const &w90_path_and_seedname) {
106
107 // open the file
108 std::string hr_filename = w90_path_and_seedname + "_hr.dat";
109 std::ifstream file(hr_filename);
110 if (!file.is_open()) throw "Could not open *_hr.dat file with provided seedname: " + w90_path_and_seedname;
111
112 // skip first line, it's a 5 item line of the date / time
113 for ([[maybe_unused]] auto i : detail::read_N<std::string>(file, 5)) {}
114
115 // next two lines have number of wannier centers, number of R vectors
116 int n_wannier = detail::read<int>(file);
117 int n_r = detail::read<int>(file);
118
119 // read in the R vector degeneracies
120 std::vector<int> r_degeneracies;
121 for (auto i : detail::read_N<int>(file, n_r)) { r_degeneracies.push_back(i); };
122
123 // set up containers for R and H_r
124 std::vector<std::array<long, 3>> r_vectors;
125 std::vector<nda::array<dcomplex, 2>> H_r;
126 for ([[maybe_unused]] auto r : nda::range(n_r)) {
127 r_vectors.emplace_back(std::array<long, 3>{0, 0, 0});
128 H_r.emplace_back(n_wannier, n_wannier);
129 }
130
131 // read the R vectors and the Wannier Hamiltonian -------
132 std::array<long, 3> R{};
133 for (auto [ir, _unused1, _unused2] : product(nda::range(n_r), nda::range(n_wannier), nda::range(n_wannier))) {
134
135 double re = 0.0, im = 0.0;
136 int ii = 0, jj = 0; // read these from the file rather than as loop indices
137 file >> R[0] >> R[1] >> R[2] >> ii >> jj >> re >> im;
138
139 // check state
140 // NB if we want to use ws_cells vec data, we will likely want to use all wannier indices instead
141 // (wannier90 indexes this from 1)
142 if ((ii == 1) and (jj == 1))
143 for (int i : {0, 1, 2}) r_vectors[ir][i] = R[i];
144
145 // merge degeneracy vector into Wannier Hamiltonian (note, W90 indexes from 1)
146 H_r[ir](ii - 1, jj - 1) = dcomplex{re, im} / r_degeneracies[ir];
147 }
148 return {std::move(r_vectors), std::move(H_r)};
149 }
150} // namespace triqs::experimental::lattice
Compiler / platform glue and the dcomplex alias (must be included before any Boost header).
w90_hr_data_t read_wannier90_hr_data(std::string const &w90_path_and_seedname)
Read a Wannier90 *_hr.dat file and return the lattice vectors and hopping matrices.
std::tuple< r_vector_list_t, hopping_list_t, position_op_list_t, nda::matrix< double > > w90_tb_data_t
Data read from a Wannier90 *_tb.dat file: lattice vectors, hopping matrices, position operators and U...
w90_tb_data_t read_wannier90_tb_data(std::string const &w90_path_and_seedname)
Read a Wannier90 *_tb.dat file and return the lattice vectors, hopping matrices, position operators a...
std::tuple< r_vector_list_t, hopping_list_t > w90_hr_data_t
Data read from a Wannier90 *_hr.dat file: lattice vectors and hopping matrices.
Portable generator alias: prefers C++23 std::generator, falls back to cppcoro::generator.