32#include <rapidxml.hpp>
34namespace pseudopotential {
36class psml :
public pseudopotential::anygrid {
39 psml(
const std::string &filename,
bool uniform_grid =
false)
40 : pseudopotential::anygrid(uniform_grid), file_(filename.c_str()),
41 buffer_((std::istreambuf_iterator<char>(file_)),
42 std::istreambuf_iterator<char>()) {
46 buffer_.push_back(
'\0');
47 doc_.parse<0>(&buffer_[0]);
49 root_node_ = doc_.first_node(
"psml");
51 spec_node_ = root_node_->first_node(
"pseudo-atom-spec");
54 spec_node_ = root_node_->first_node(
"header");
58 bool has_local_potential = root_node_->first_node(
"local-potential");
59 bool has_nl_projectors = select_set_node(
"nonlocal-projectors");
60 bool has_semilocal_potentials = select_set_node(
"semilocal-potentials");
61 bool has_pseudo_wavefunctions = select_set_node(
"pseudo-wave-functions");
62 if (has_nl_projectors && has_local_potential) {
63 type_ = pseudopotential::type::KLEINMAN_BYLANDER;
64 }
else if (has_semilocal_potentials && has_pseudo_wavefunctions) {
65 type_ = pseudopotential::type::SEMILOCAL;
67 throw status::UNSUPPORTED_TYPE;
73 if (type_ == pseudopotential::type::KLEINMAN_BYLANDER) {
74 tag1 =
"nonlocal-projectors";
76 }
else if (type_ == pseudopotential::type::SEMILOCAL) {
77 tag1 =
"semilocal-potentials";
84 rapidxml::xml_node<> *node = select_set_node(tag1.c_str());
86 node = node->first_node(tag2.c_str());
88 int read_l = letter_to_l(node->first_attribute(
"l")->value());
89 lmax_ = std::max(lmax_, read_l);
90 node = node->next_sibling(tag2.c_str());
98 rapidxml::xml_node<> *node = root_node_->first_node(
"grid");
102 int size = value<int>(node->first_attribute(
"npts"));
104 std::istringstream stst(node->first_node(
"grid-data")->value());
105 for (
int ii = 0; ii < size; ii++) {
108 assert(grid_[ii] > grid_[ii - 1]);
111 assert(
fabs(grid_[0]) <= 1e-10);
114 for (
double rr = 0.0; rr <= grid_[grid_.size() - 1]; rr += mesh_spacing())
117 grid_weights_.resize(grid_.size());
120 grid_weights_[0] = 0.5 * (grid_[1] - grid_[0]);
121 for (
unsigned ii = 1; ii < grid_.size() - 1; ii++)
122 grid_weights_[ii] = grid_[ii + 1] - grid_[ii - 1];
123 grid_weights_[grid_.size() - 1] =
124 0.5 * (grid_[grid_.size() - 1] - grid_[grid_.size() - 2]);
128 pseudopotential::format format()
const {
129 return pseudopotential::format::PSML;
132 int size()
const {
return buffer_.size(); };
137 return element::trim(spec_node_->first_attribute(
"atomic-label")->value());
140 int atomic_number()
const {
141 return value<int>(spec_node_->first_attribute(
"atomic-number"));
144 double mass()
const {
145 element el(symbol());
149 double valence_charge()
const {
150 return value<double>(spec_node_->first_node(
"valence-configuration")
151 ->first_attribute(
"total-valence-charge"));
154 int llocal()
const {
return -1; }
156 pseudopotential::exchange exchange()
const {
158 rapidxml::xml_node<> *node = spec_node_->first_node(
"exchange-correlation")
159 ->first_node(
"libxc-info")
160 ->first_node(
"functional");
162 if (value<std::string>(node->first_attribute(
"type")) ==
"exchange") {
163 return pseudopotential::exchange(
164 value<int>(node->first_attribute(
"id")));
166 node = node->next_sibling(
"functional");
168 return pseudopotential::exchange::UNKNOWN;
171 pseudopotential::correlation correlation()
const {
173 rapidxml::xml_node<> *node = spec_node_->first_node(
"exchange-correlation")
174 ->first_node(
"libxc-info")
175 ->first_node(
"functional");
177 if (value<std::string>(node->first_attribute(
"type")) ==
"correlation") {
178 return pseudopotential::correlation(
179 value<int>(node->first_attribute(
"id")));
181 node = node->next_sibling(
"functional");
183 return pseudopotential::correlation::UNKNOWN;
186 int nchannels()
const {
187 if (type_ == pseudopotential::type::SEMILOCAL)
189 if (is_fully_relativistic()) {
191 for (
int l = 0;
l <= lmax_;
l++)
192 nc = std::max(nc, nprojectors_per_l(
l));
197 rapidxml::xml_node<> *node = nonlocal_projectors_node();
199 node = node->first_node(
"proj");
201 int read_ic = value<int>(node->first_attribute(
"seq")) - 1;
202 nc = std::max(nc, read_ic + 1);
203 node = node->next_sibling(
"proj");
208 void local_potential(std::vector<double> &val)
const {
209 read_function(root_node_->first_node(
"local-potential"), val,
true);
212 int nprojectors()
const {
213 rapidxml::xml_node<> *node =
214 nonlocal_projectors_node()->first_node(
"proj");
218 node = node->next_sibling(
"proj");
223 int nprojectors_per_l(
int l)
const {
224 if (type_ == pseudopotential::type::SEMILOCAL)
227 rapidxml::xml_node<> *node =
228 nonlocal_projectors_node()->first_node(
"proj");
231 int read_l = letter_to_l(node->first_attribute(
"l")->value());
232 if (read_l ==
l) count++;
233 node = node->next_sibling(
"proj");
239 void projector(
int l,
int ic, std::vector<double> &val)
const {
240 rapidxml::xml_node<> *node = projector_node(
l, ic);
241 read_function(node, val);
244 double d_ij(
int l,
int ic,
int jc)
const {
248 rapidxml::xml_node<> *node = projector_node(
l, ic);
251 return value<double>(node->first_attribute(
"ekb"));
254 bool has_radial_function(
int l)
const {
255 return wavefunction_node_for_l(
l) !=
nullptr;
258 void radial_function(
int l, std::vector<double> &val)
const {
259 rapidxml::xml_node<> *node = wavefunction_node_for_l(
l);
260 read_function(node, val);
263 void radial_potential(
int l, std::vector<double> &val)
const {
264 rapidxml::xml_node<> *node =
265 semilocal_potentials_node()->first_node(
"slps");
267 int read_l = letter_to_l(node->first_attribute(
"l")->value());
270 node = node->next_sibling(
"slps");
272 read_function(node, val);
275 bool has_nlcc()
const {
276 rapidxml::xml_node<> *node = root_node_->first_node(
"pseudocore-charge");
280 void nlcc_density(std::vector<double> &val)
const {
281 read_function(root_node_->first_node(
"pseudocore-charge"), val);
282 for (
unsigned ii = 0; ii < val.size(); ii++)
283 val[ii] /= 4.0 * M_PI;
286 bool has_density() {
return root_node_->first_node(
"valence-charge"); }
288 void density(std::vector<double> &val)
const {
289 read_function(root_node_->first_node(
"valence-charge"), val);
290 for (
unsigned ii = 0; ii < val.size(); ii++)
291 val[ii] /= 4.0 * M_PI;
294 bool has_total_angular_momentum()
const {
295 return spec_node_->first_attribute(
"relativity")->value() ==
299 int projector_2j(
int l,
int ic)
const {
300 rapidxml::xml_node<> *node = projector_node(
l, ic);
302 double read_j = value<double>(node->first_attribute(
"j"));
303 return lrint(2.0 * read_j);
306 int nwavefunctions()
const {
307 rapidxml::xml_node<> *wf_set = pseudo_wavefunctions_node();
312 for (rapidxml::xml_node<> *shell = first_valence_shell();
313 shell; shell = shell->next_sibling(
"shell")) {
314 rapidxml::xml_node<> *node = wf_set->first_node(
"pswf");
316 if (wavefunction_matches_shell(node, shell))
318 node = node->next_sibling(
"pswf");
326 rapidxml::xml_node<> *node = wf_set->first_node(
"pswf");
329 node = node->next_sibling(
"pswf");
334 void wavefunction(
int index,
int &n,
int &
l,
double &occ,
335 std::vector<double> &val)
const {
336 rapidxml::xml_node<> *node = wavefunction_node(
index);
339 n = value<int>(node->first_attribute(
"n"));
340 l = letter_to_l(node->first_attribute(
"l")->value());
341 occ = wavefunction_occupation(node);
343 read_function(node, val);
346 int wavefunction_2j(
int ii)
const {
347 rapidxml::xml_node<> *node = wavefunction_node(ii - 1);
350 auto *j_attr = node->first_attribute(
"j");
354 return lrint(2.0 * value<double>(j_attr));
358 bool is_fully_relativistic()
const {
359 auto *attr = spec_node_->first_attribute(
"relativity");
360 return attr &&
std::string(attr->value()) ==
"dirac";
363 rapidxml::xml_node<> *select_set_node(
const char *name)
const {
364 rapidxml::xml_node<> *node = root_node_->first_node(name);
365 rapidxml::xml_node<> *fallback =
nullptr;
367 is_fully_relativistic() ?
"lj" :
"scalar_relativistic";
370 auto *set_attr = node->first_attribute(
"set");
375 if (set_name == preferred_set)
377 if (set_name ==
"scalar_relativistic" && fallback ==
nullptr)
379 if (fallback ==
nullptr)
382 node = node->next_sibling(name);
388 rapidxml::xml_node<> *nonlocal_projectors_node()
const {
389 return select_set_node(
"nonlocal-projectors");
392 rapidxml::xml_node<> *semilocal_potentials_node()
const {
393 return select_set_node(
"semilocal-potentials");
396 rapidxml::xml_node<> *pseudo_wavefunctions_node()
const {
397 return select_set_node(
"pseudo-wave-functions");
400 rapidxml::xml_node<> *projector_node(
int l,
int ic)
const {
402 rapidxml::xml_node<> *node = nonlocal_projectors_node()->first_node(
"proj");
407 if (is_fully_relativistic() &&
l > 0) {
408 desired_seq = ic / 2 + 1;
409 desired_2j = (ic % 2 == 0) ? 2 *
l + 1 : 2 *
l - 1;
413 int read_l = letter_to_l(node->first_attribute(
"l")->value());
415 if (is_fully_relativistic()) {
417 if (current_ic == ic)
421 int read_ic = value<int>(node->first_attribute(
"seq"));
422 int read_2j = lrint(2.0 * value<double>(node->first_attribute(
"j")));
423 if (read_ic == desired_seq && read_2j == desired_2j)
427 int read_ic = value<int>(node->first_attribute(
"seq")) - 1;
432 node = node->next_sibling(
"proj");
438 rapidxml::xml_node<> *first_valence_shell()
const {
439 rapidxml::xml_node<> *node = spec_node_->first_node(
"valence-configuration");
442 return node->first_node(
"shell");
445 bool wavefunction_matches_shell(rapidxml::xml_node<> *wavefunction,
446 rapidxml::xml_node<> *shell)
const {
447 assert(wavefunction);
450 return value<int>(wavefunction->first_attribute(
"n")) ==
451 value<int>(shell->first_attribute(
"n")) &&
452 std::string(wavefunction->first_attribute(
"l")->value()) ==
453 shell->first_attribute(
"l")->value();
456 double wavefunction_occupation(rapidxml::xml_node<> *wavefunction)
const {
457 assert(wavefunction);
459 auto *occupation_attr = wavefunction->first_attribute(
"occupation");
461 return value<double>(occupation_attr);
463 rapidxml::xml_node<> *shell = first_valence_shell();
465 if (wavefunction_matches_shell(wavefunction, shell)) {
466 double occupation = value<double>(shell->first_attribute(
"occupation"));
467 auto *j_attr = wavefunction->first_attribute(
"j");
471 double j = value<double>(j_attr);
472 int l = letter_to_l(wavefunction->first_attribute(
"l")->value());
473 return occupation * (2.0 *
j + 1.0) / (2.0 * (2.0 *
l + 1.0));
475 shell = shell->next_sibling(
"shell");
481 rapidxml::xml_node<> *wavefunction_node_for_l(
int l)
const {
482 rapidxml::xml_node<> *wf_set = pseudo_wavefunctions_node();
486 rapidxml::xml_node<> *node = wf_set->first_node(
"pswf");
488 int read_l = letter_to_l(node->first_attribute(
"l")->value());
490 rapidxml::xml_node<> *shell = first_valence_shell();
492 if (wavefunction_matches_shell(node, shell))
494 shell = shell->next_sibling(
"shell");
498 node = node->next_sibling(
"pswf");
504 rapidxml::xml_node<> *wavefunction_node(
int index)
const {
505 rapidxml::xml_node<> *wf_set = pseudo_wavefunctions_node();
509 for (rapidxml::xml_node<> *shell = first_valence_shell();
510 shell; shell = shell->next_sibling(
"shell")) {
511 rapidxml::xml_node<> *best_high_j =
nullptr;
512 rapidxml::xml_node<> *best_low_j =
nullptr;
514 for (rapidxml::xml_node<> *node = wf_set->first_node(
"pswf"); node;
515 node = node->next_sibling(
"pswf")) {
516 if (!wavefunction_matches_shell(node, shell))
519 auto *j_attr = node->first_attribute(
"j");
521 if (current ==
index)
527 double j = value<double>(j_attr);
528 int shell_l = letter_to_l(shell->first_attribute(
"l")->value());
536 if (current ==
index)
541 if (current ==
index)
547 for (rapidxml::xml_node<> *node = wf_set->first_node(
"pswf"); node;
548 node = node->next_sibling(
"pswf")) {
549 if (current ==
index)
557 void read_function(rapidxml::xml_node<> *base_node, std::vector<double> &val,
558 bool potential_padding =
false)
const {
560 rapidxml::xml_node<> *node =
561 base_node->first_node(
"radfunc")->first_node(
"data");
563 int size = grid_.size();
564 if (node->first_attribute(
"npts"))
565 size = value<int>(node->first_attribute(
"npts"));
566 val.resize(grid_.size());
567 std::istringstream stst(node->value());
568 for (
int ii = 0; ii < size; ii++)
571 if (potential_padding) {
572 for (
unsigned ii = size; ii < grid_.size(); ii++)
573 val[ii] = -valence_charge() / grid_[ii];
575 for (
unsigned ii = size; ii < grid_.size(); ii++)
584 static int letter_to_l(
const std::string &letter) {
601 std::vector<char> buffer_;
602 rapidxml::xml_document<> doc_;
603 rapidxml::xml_node<> *root_node_;
604 rapidxml::xml_node<> *spec_node_;
if write to the Free Software Franklin Fifth USA !If the compiler accepts long Fortran it is better to use that and build all the preprocessor definitions in one line In !this the debuggers will provide the right line numbers !If the compiler accepts line number then CARDINAL and ACARDINAL !will put them just a new line or a ampersand plus a new line !These macros should be used in macros that span several lines They should by !put immedialty before a line where a compilation error might occur and at the !end of the macro !Note that the cardinal and newline words are substituted by the program !preprocess pl by the ampersand and by a real new line just before compilation !The assertions are ignored if the code is compiled in not debug when !prints out the assertion string
double fabs(double __x) __attribute__((__nothrow__
const int *restrict index