36 const std::string& file_content,
37 const std::string& source_description)
38 : pseudopotential_(pseudopotential)
39 , content_(file_content)
40 , source_description_(source_description) {}
45 read_core_charge_density();
46 read_local_potential();
47 read_beta_projectors();
49 read_pseudo_wavefunctions();
50 read_atomic_charge_density();
55 using namespace upf_utilities;
56 auto position = content_.find(
"<PP_HEADER");
57 if (position == std::string::npos)
58 throw std::runtime_error(
"No PP_HEADER found in UPF v2 file");
59 auto end_position = content_.find(
"/>", position);
60 if (end_position == std::string::npos)
61 end_position = content_.find(
">", position);
62 std::string header_tag = content_.substr(position, end_position - position + 2);
64 pseudopotential_.
element = xml_attribute(header_tag,
"element");
66 while (!pseudopotential_.
element.empty() && pseudopotential_.
element.back() ==
' ')
67 pseudopotential_.
element.pop_back();
68 while (!pseudopotential_.
element.empty() && pseudopotential_.
element.front() ==
' ')
72 canonical_pseudopotential_type(xml_attribute(header_tag,
"pseudo_type"));
74 required_real_attribute(header_tag,
"z_valence", source_description_);
76 required_integer_attribute(header_tag,
"mesh_size", source_description_);
78 required_integer_attribute(header_tag,
"number_of_proj", source_description_);
80 required_integer_attribute(header_tag,
"l_max", source_description_);
82 std::string core_correction = xml_attribute(header_tag,
"core_correction");
84 (core_correction ==
"T" || core_correction ==
"t" || core_correction ==
"true" ||
85 core_correction ==
"True");
87 pseudopotential_.
xc_functional = xml_attribute(header_tag,
"functional");
89 std::string number_of_wavefunctions_string = xml_attribute(header_tag,
"number_of_wfc");
90 if (!number_of_wavefunctions_string.empty())
93 log::info(
" UPFv2: {} ({}) Z={} mesh={} num_beta={} max_l={} has_nlcc={}",
104 using namespace upf_utilities;
106 auto mesh_position = content_.find(
"<PP_MESH");
107 if (mesh_position != std::string::npos) {
108 auto tag_end = content_.find(
">", mesh_position);
109 std::string tag_line = content_.substr(mesh_position, tag_end - mesh_position);
110 std::string mesh_attribute = xml_attribute(tag_line,
"mesh");
111 if (!mesh_attribute.empty()) {
112 pseudopotential_.
mesh_size = std::stoi(mesh_attribute);
117 auto position = content_.find(
"<PP_R ");
118 if (position == std::string::npos)
119 position = content_.find(
"<PP_R>");
120 if (position != std::string::npos) {
121 auto end_position = content_.find(
"</PP_R>", position);
122 std::string
section = content_.substr(position, end_position - position);
127 position = content_.find(
"<PP_RAB ");
128 if (position == std::string::npos)
129 position = content_.find(
"<PP_RAB>");
130 if (position != std::string::npos) {
131 auto end_position = content_.find(
"</PP_RAB>", position);
132 std::string
section = content_.substr(position, end_position - position);
137 void read_core_charge_density() {
138 using namespace upf_utilities;
141 auto position = content_.find(
"<PP_NLCC");
142 if (position != std::string::npos) {
143 auto end_position = content_.find(
"</PP_NLCC>", position);
144 std::string
section = content_.substr(position, end_position - position);
149 void read_local_potential() {
150 using namespace upf_utilities;
151 auto position = content_.find(
"<PP_LOCAL");
152 if (position != std::string::npos) {
153 auto end_position = content_.find(
"</PP_LOCAL>", position);
154 std::string
section = content_.substr(position, end_position - position);
159 void read_beta_projectors() {
160 using namespace upf_utilities;
163 std::string tag =
"<PP_BETA." + std::to_string(beta_index + 1);
164 auto position = content_.find(tag);
165 if (position == std::string::npos) {
166 throw std::runtime_error(
"Cannot find " + tag +
" in UPF v2 file");
170 auto tag_end = content_.find(
">", position);
171 std::string tag_line = content_.substr(position, tag_end - position);
173 std::string angular_momentum_string =
xml_attribute(tag_line,
"angular_momentum");
174 pseudopotential_.
projectors[beta_index].angular_momentum =
175 angular_momentum_string.empty() ? 0 : std::stoi(angular_momentum_string);
177 std::string cutoff_index_string =
xml_attribute(tag_line,
"cutoff_radius_index");
178 pseudopotential_.
projectors[beta_index].number_of_radial_cutoff_points =
179 cutoff_index_string.empty() ? pseudopotential_.
mesh_size
180 : std::stoi(cutoff_index_string);
183 auto close_position =
184 content_.find(
"</PP_BETA." + std::to_string(beta_index + 1) +
">", position);
185 if (close_position == std::string::npos) {
187 close_position = content_.find(
"</PP_BETA>", position);
189 std::string
section = content_.substr(tag_end + 1, close_position - tag_end - 1);
198 void read_d_matrix() {
199 using namespace upf_utilities;
200 auto position = content_.find(
"<PP_DIJ");
201 if (position != std::string::npos) {
202 auto end_position = content_.find(
"</PP_DIJ>", position);
203 std::string
section = content_.substr(position, end_position - position);
204 std::vector<Real> dij_flat =
xml_data(section);
211 flat_index < static_cast<int>(dij_flat.size());
214 flat_index < static_cast<int>(dij_flat.size());
216 pseudopotential_.
d_ion_matrix[row][column] = dij_flat[flat_index++];
222 void read_pseudo_wavefunctions() {
223 using namespace upf_utilities;
224 auto position = content_.find(
"<PP_PSWFC>");
225 if (position == std::string::npos)
226 position = content_.find(
"<PP_PSWFC ");
227 if (position == std::string::npos)
230 auto end_pswfc = content_.find(
"</PP_PSWFC>", position);
231 if (end_pswfc == std::string::npos)
235 for (
int wavefunction_index = 0;
237 wavefunction_index++) {
238 std::string tag =
"<PP_CHI." + std::to_string(wavefunction_index + 1);
239 auto wavefunction_position = content_.find(tag, position);
240 if (wavefunction_position == std::string::npos || wavefunction_position >= end_pswfc)
243 auto wavefunction_tag_end = content_.find(
">", wavefunction_position);
244 std::string tag_line = content_.substr(wavefunction_position,
245 wavefunction_tag_end - wavefunction_position);
249 std::string angular_momentum_string =
xml_attribute(tag_line,
" l");
250 if (angular_momentum_string.empty())
252 if (angular_momentum_string.empty())
255 angular_momentum_string.empty() ? 0 : std::stoi(angular_momentum_string);
256 std::string occupation_string =
xml_attribute(tag_line,
"occupation");
258 occupation_string.empty() ? 0.0 : std::stod(occupation_string);
260 std::string close_tag =
"</PP_CHI." + std::to_string(wavefunction_index + 1) +
">";
261 auto wavefunction_end = content_.find(close_tag, wavefunction_position);
262 if (wavefunction_end == std::string::npos)
263 wavefunction_end = content_.find(
"</PP_CHI>", wavefunction_position);
265 if (wavefunction_end != std::string::npos) {
266 std::string
section = content_.substr(wavefunction_tag_end + 1,
267 wavefunction_end - wavefunction_tag_end - 1);
276 void read_atomic_charge_density() {
277 using namespace upf_utilities;
278 auto position = content_.find(
"<PP_RHOATOM");
279 if (position != std::string::npos) {
280 auto end_position = content_.find(
"</PP_RHOATOM>", position);
281 std::string
section = content_.substr(position, end_position - position);
286 Pseudopotential& pseudopotential_;
287 const std::string& content_;
288 std::string source_description_;