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 = root_node_->first_node(
"nonlocal-projectors");
 
   60    bool has_semilocal_potentials =
 
   61        root_node_->first_node(
"semilocal-potentials");
 
   62    bool has_pseudo_wavefunctions =
 
   63        root_node_->first_node(
"pseudo-wave-functions");
 
   64    if (has_nl_projectors && has_local_potential) {
 
   65      type_ = pseudopotential::type::KLEINMAN_BYLANDER;
 
   66    } 
else if (has_semilocal_potentials && has_pseudo_wavefunctions) {
 
   67      type_ = pseudopotential::type::SEMILOCAL;
 
   69      throw status::UNSUPPORTED_TYPE;
 
   75      if (type_ == pseudopotential::type::KLEINMAN_BYLANDER) {
 
   76        tag1 = 
"nonlocal-projectors";
 
   78      } 
else if (type_ == pseudopotential::type::SEMILOCAL) {
 
   79        tag1 = 
"semilocal-potentials";
 
   86      rapidxml::xml_node<> *node = root_node_->first_node(tag1.c_str());
 
   88      node = node->first_node(tag2.c_str());
 
   90        int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
   91        lmax_ = std::max(lmax_, read_l);
 
   92        node = node->next_sibling(tag2.c_str());
 
  100      rapidxml::xml_node<> *node = root_node_->first_node(
"grid");
 
  104      int size = value<int>(node->first_attribute(
"npts"));
 
  106      std::istringstream stst(node->first_node(
"grid-data")->value());
 
  107      for (
int ii = 0; ii < size; ii++) {
 
  110          assert(grid_[ii] > grid_[ii - 1]);
 
  113      assert(
fabs(grid_[0]) <= 1e-10);
 
  116      for (
double rr = 0.0; rr <= grid_[grid_.size() - 1]; rr += mesh_spacing())
 
  119      grid_weights_.resize(grid_.size());
 
  122      grid_weights_[0] = 0.5 * (grid_[1] - grid_[0]);
 
  123      for (
unsigned ii = 1; ii < grid_.size() - 1; ii++)
 
  124        grid_weights_[ii] = grid_[ii + 1] - grid_[ii - 1];
 
  125      grid_weights_[grid_.size() - 1] =
 
  126          0.5 * (grid_[grid_.size() - 1] - grid_[grid_.size() - 2]);
 
  130  pseudopotential::format format()
 const {
 
  131    return pseudopotential::format::PSML;
 
  134  int size()
 const { 
return buffer_.size(); };
 
  139    return element::trim(spec_node_->first_attribute(
"atomic-label")->value());
 
  142  int atomic_number()
 const {
 
  143    return value<int>(spec_node_->first_attribute(
"atomic-number"));
 
  146  double mass()
 const {
 
  147    element el(symbol());
 
  151  double valence_charge()
 const {
 
  152    return value<double>(spec_node_->first_node(
"valence-configuration")
 
  153                             ->first_attribute(
"total-valence-charge"));
 
  156  int llocal()
 const { 
return -1; }
 
  158  pseudopotential::exchange exchange()
 const {
 
  160    rapidxml::xml_node<> *node = spec_node_->first_node(
"exchange-correlation")
 
  161                                     ->first_node(
"libxc-info")
 
  162                                     ->first_node(
"functional");
 
  164      if (value<std::string>(node->first_attribute(
"type")) == 
"exchange") {
 
  165        return pseudopotential::exchange(
 
  166            value<int>(node->first_attribute(
"id")));
 
  168      node = node->next_sibling(
"functional");
 
  170    return pseudopotential::exchange::UNKNOWN;
 
  173  pseudopotential::correlation correlation()
 const {
 
  175    rapidxml::xml_node<> *node = spec_node_->first_node(
"exchange-correlation")
 
  176                                     ->first_node(
"libxc-info")
 
  177                                     ->first_node(
"functional");
 
  179      if (value<std::string>(node->first_attribute(
"type")) == 
"correlation") {
 
  180        return pseudopotential::correlation(
 
  181            value<int>(node->first_attribute(
"id")));
 
  183      node = node->next_sibling(
"functional");
 
  185    return pseudopotential::correlation::UNKNOWN;
 
  188  int nchannels()
 const {
 
  189    if (type_ == pseudopotential::type::SEMILOCAL)
 
  192    rapidxml::xml_node<> *node = root_node_->first_node(
"nonlocal-projectors");
 
  194    node = node->first_node(
"proj");
 
  196      int read_ic = value<int>(node->first_attribute(
"seq")) - 1;
 
  197      nc = std::max(nc, read_ic + 1);
 
  198      node = node->next_sibling(
"proj");
 
  203  void local_potential(std::vector<double> &val)
 const {
 
  204    read_function(root_node_->first_node(
"local-potential"), val, 
true);
 
  207  int nprojectors()
 const {
 
  208    rapidxml::xml_node<> *node =
 
  209        root_node_->first_node(
"nonlocal-projectors")->first_node(
"proj");
 
  213      node = node->next_sibling(
"proj");
 
  218  int nprojectors_per_l(
int l)
 const {
 
  219    if (type_ == pseudopotential::type::SEMILOCAL)
 
  222    rapidxml::xml_node<> *node =
 
  223        root_node_->first_node(
"nonlocal-projectors")->first_node(
"proj");
 
  226      int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
  227      if (read_l == 
l) count++; 
 
  228      node = node->next_sibling(
"proj");
 
  234  void projector(
int l, 
int ic, std::vector<double> &val)
 const {
 
  235    rapidxml::xml_node<> *node =
 
  236        root_node_->first_node(
"nonlocal-projectors")->first_node(
"proj");
 
  238      int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
  239      int read_ic = value<int>(node->first_attribute(
"seq")) - 1;
 
  240      if (
l == read_l && ic == read_ic)
 
  242      node = node->next_sibling(
"proj");
 
  244    read_function(node, val);
 
  247  double d_ij(
int l, 
int ic, 
int jc)
 const {
 
  251    rapidxml::xml_node<> *node =
 
  252        root_node_->first_node(
"nonlocal-projectors")->first_node(
"proj");
 
  254      int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
  255      int read_ic = value<int>(node->first_attribute(
"seq")) - 1;
 
  256      if (
l == read_l && ic == read_ic)
 
  258      node = node->next_sibling(
"proj");
 
  261    return value<double>(node->first_attribute(
"ekb"));
 
  264  bool has_radial_function(
int l)
 const { 
return false; }
 
  266  void radial_function(
int l, std::vector<double> &val)
 const {
 
  267    rapidxml::xml_node<> *node =
 
  268        root_node_->first_node(
"pseudo-wave-functions")->first_node(
"pswf");
 
  270      int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
  273      node = node->next_sibling(
"pswf");
 
  275    read_function(node, val);
 
  278  void radial_potential(
int l, std::vector<double> &val)
 const {
 
  279    rapidxml::xml_node<> *node =
 
  280        root_node_->first_node(
"semilocal-potentials")->first_node(
"slps");
 
  282      int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
  285      node = node->next_sibling(
"slps");
 
  287    read_function(node, val);
 
  290  bool has_nlcc()
 const {
 
  291    rapidxml::xml_node<> *node = root_node_->first_node(
"pseudocore-charge");
 
  295  void nlcc_density(std::vector<double> &val)
 const {
 
  296    read_function(root_node_->first_node(
"pseudocore-charge"), val);
 
  297    for (
unsigned ii = 0; ii < val.size(); ii++)
 
  298      val[ii] /= 4.0 * M_PI;
 
  301  bool has_density() { 
return root_node_->first_node(
"valence-charge"); }
 
  303  void density(std::vector<double> &val)
 const {
 
  304    read_function(root_node_->first_node(
"valence-charge"), val);
 
  305    for (
unsigned ii = 0; ii < val.size(); ii++)
 
  306      val[ii] /= 4.0 * M_PI;
 
  309  bool has_total_angular_momentum()
 const {
 
  310    return spec_node_->first_attribute(
"relativity")->value() ==
 
  314  int projector_2j(
int l, 
int ic)
 const {
 
  315    rapidxml::xml_node<> *node =
 
  316        root_node_->first_node(
"nonlocal-projectors")->first_node(
"proj");
 
  318      int read_l = letter_to_l(node->first_attribute(
"l")->value());
 
  319      int read_ic = value<int>(node->first_attribute(
"seq")) - 1;
 
  320      if (
l == read_l && ic == read_ic) {
 
  321        double read_j = value<double>(node->first_attribute(
"j"));
 
  322        std::cout << 
l << 
" " << ic << 
" " << read_j << std::endl;
 
  323        return lrint(2.0 * read_j);
 
  325      node = node->next_sibling(
"proj");
 
  332  void read_function(rapidxml::xml_node<> *base_node, std::vector<double> &val,
 
  333                     bool potential_padding = 
false)
 const {
 
  335    rapidxml::xml_node<> *node =
 
  336        base_node->first_node(
"radfunc")->first_node(
"data");
 
  338    int size = grid_.size();
 
  339    if (node->first_attribute(
"npts"))
 
  340      size = value<int>(node->first_attribute(
"npts"));
 
  341    val.resize(grid_.size());
 
  342    std::istringstream stst(node->value());
 
  343    for (
int ii = 0; ii < size; ii++)
 
  346    if (potential_padding) {
 
  347      for (
unsigned ii = size; ii < grid_.size(); ii++)
 
  348        val[ii] = -valence_charge() / grid_[ii];
 
  350      for (
unsigned ii = size; ii < grid_.size(); ii++)
 
  359  static int letter_to_l(
const std::string &letter) {
 
  376  std::vector<char> buffer_;
 
  377  rapidxml::xml_document<> doc_;
 
  378  rapidxml::xml_node<> *root_node_;
 
  379  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__
 
integer, parameter, public density
 
integer, parameter, public mass