37 : pseudopotential_(pseudopotential), file_stream_(file_stream) {}
45 reconstruct_l_resolved_qfuncl();
49 void read_qij_header() {
50 using namespace upf_utilities;
52 file_stream_.seekg(0);
53 if (!find_tag(file_stream_,
"<PP_QIJ>"))
54 throw std::runtime_error(
"PP_QIJ section not found for ultrasoft PP");
56 std::string header_line;
57 std::getline(file_stream_, header_line);
59 std::istringstream stream(header_line);
66 number_of_betas, std::vector<Real>(number_of_betas, 0.0));
73 using namespace upf_utilities;
78 file_stream_.seekg(0);
79 if (
find_tag(file_stream_,
"<PP_RINNER>")) {
81 for (
int angular_momentum = 0; angular_momentum < number_of_rinner_entries;
83 int angular_momentum_index;
85 file_stream_ >> angular_momentum_index >> inner_radius;
92 void read_qij_data() {
93 using namespace upf_utilities;
99 file_stream_.seekg(0);
102 std::vector<std::string> qij_lines;
105 std::getline(file_stream_, line);
106 bool inside_rinner_section =
false;
107 while (std::getline(file_stream_, line)) {
108 if (line.find(
"</PP_QIJ>") != std::string::npos)
110 if (line.find(
"<PP_RINNER>") != std::string::npos) {
111 inside_rinner_section =
true;
114 if (line.find(
"</PP_RINNER>") != std::string::npos) {
115 inside_rinner_section =
false;
118 if (inside_rinner_section)
120 if (line.find(
"<PP_QFCOEF>") != std::string::npos) {
121 qij_lines.push_back(
"__QFCOEF_BEGIN__");
124 if (line.find(
"</PP_QFCOEF>") != std::string::npos) {
125 qij_lines.push_back(
"__QFCOEF_END__");
128 qij_lines.push_back(line);
133 size_t line_index = 0;
134 auto next_non_empty_line = [&]() -> std::string {
135 while (line_index < qij_lines.size()) {
136 std::string trimmed =
trim(qij_lines[line_index++]);
137 if (!trimmed.empty())
142 auto read_reals_from_lines = [&](
int count) -> std::vector<Real> {
143 std::vector<Real> values;
144 values.reserve(count);
145 while (
static_cast<int>(values.size()) < count && line_index < qij_lines.size()) {
146 const std::string& raw = qij_lines[line_index];
147 if (raw ==
"__QFCOEF_BEGIN__" || raw ==
"__QFCOEF_END__") {
151 std::istringstream stream(raw);
153 while (
static_cast<int>(values.size()) < count && stream >> value) {
154 values.push_back(value);
162 for (
int beta_index_1 = 0; beta_index_1 < number_of_betas; beta_index_1++) {
163 for (
int beta_index_2 = beta_index_1; beta_index_2 < number_of_betas; beta_index_2++) {
165 next_non_empty_line();
168 std::string q_integral_line = next_non_empty_line();
170 std::istringstream stream(q_integral_line);
177 int pair_index = beta_index_1 * number_of_betas + beta_index_2;
178 int symmetric_pair_index = beta_index_2 * number_of_betas + beta_index_1;
182 read_reals_from_lines(pseudopotential_.
mesh_size);
189 while (line_index < qij_lines.size() &&
190 qij_lines[line_index] ==
"__QFCOEF_BEGIN__")
195 for (
int angular_momentum = 0;
197 angular_momentum++) {
205 while (line_index < qij_lines.size() &&
206 qij_lines[line_index] ==
"__QFCOEF_END__")
212 log::info(
" PP {}: {} Q_ij pairs read, nqf={}",
214 number_of_betas * (number_of_betas + 1) / 2,
218 void reconstruct_l_resolved_qfuncl() {
245 for (
auto& entry : pseudopotential_.augmentation_function_by_angular_momentum)
246 entry.resize(pseudopotential_.number_of_q_angular_momenta);
248 for (
int beta_index_1 = 0; beta_index_1 < number_of_betas; beta_index_1++) {
249 for (
int beta_index_2 = beta_index_1; beta_index_2 < number_of_betas; beta_index_2++) {
250 int pair_index = beta_index_1 * number_of_betas + beta_index_2;
251 int symmetric_pair_index = beta_index_2 * number_of_betas + beta_index_1;
252 int angular_momentum_1 = pseudopotential_.
projectors[beta_index_1].angular_momentum;
253 int angular_momentum_2 = pseudopotential_.
projectors[beta_index_2].angular_momentum;
261 for (
int angular_momentum = std::abs(angular_momentum_1 - angular_momentum_2);
262 angular_momentum <= angular_momentum_1 + angular_momentum_2;
263 angular_momentum += 2) {
269 if (symmetric_pair_index != pair_index)
280 for (
int angular_momentum = std::abs(angular_momentum_1 - angular_momentum_2);
281 angular_momentum <= angular_momentum_1 + angular_momentum_2;
282 angular_momentum += 2) {
285 if (angular_momentum >=
289 if (angular_momentum >=
293 if (
static_cast<int>(
295 .augmentation_coefficients[pair_index][angular_momentum]
300 int last_inner_point = 0;
301 for (
int radial_index = 0; radial_index < pseudopotential_.
mesh_size;
305 last_inner_point = radial_index;
322 const auto& coefficients =
325 for (
int radial_index = 0; radial_index <= last_inner_point;
329 Real polynomial_value = coefficients[0];
330 for (
int coefficient_index = 1;
332 coefficient_index++) {
334 coefficients[coefficient_index] *
335 std::pow(radius_squared,
static_cast<Real>(coefficient_index));
338 Real q_value = polynomial_value *
339 std::pow(pseudopotential_.
radial_grid[radial_index],
340 angular_momentum + 2);
342 [pair_index][angular_momentum][radial_index] = q_value;
343 if (symmetric_pair_index != pair_index)
345 [symmetric_pair_index][angular_momentum][radial_index] =
352 log::info(
" PP {}: L-resolved qfuncl reconstructed from qfcoef (nqlc={})",
357 UltrasoftPseudopotential& pseudopotential_;
358 std::ifstream& file_stream_;