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