Octopus 16.0
real-space, real-time, TDDFT code
psml.hpp
Go to the documentation of this file.
1#ifndef PSEUDO_PSML_HPP
2#define PSEUDO_PSML_HPP
3
4/*
5 Copyright (C) 2018 Xavier Andrade
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#include <cassert>
23#include <cmath>
24#include <fstream>
25#include <iostream>
26#include <sstream>
27#include <vector>
28
29#include "anygrid.hpp"
30#include "base.hpp"
31#include "element.hpp"
32#include <rapidxml.hpp>
33
34namespace pseudopotential {
35
37
38public:
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>()) {
43
44 filename_ = filename;
45
46 buffer_.push_back('\0');
47 doc_.parse<0>(&buffer_[0]);
48
49 root_node_ = doc_.first_node("psml");
50
51 spec_node_ = root_node_->first_node("pseudo-atom-spec");
52 // some files do not have "pseudo-atom-spec" but "header"
53 if (!spec_node_)
54 spec_node_ = root_node_->first_node("header");
55 assert(spec_node_);
56
57 // now check the type
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) {
66 } else if (has_semilocal_potentials && has_pseudo_wavefunctions) {
68 } else {
70 }
71
72 {
73 // read lmax
74 std::string tag1, tag2;
76 tag1 = "nonlocal-projectors";
77 tag2 = "proj";
79 tag1 = "semilocal-potentials";
80 tag2 = "slps";
81 } else {
82 assert(false);
83 }
84
85 lmax_ = -1;
86 rapidxml::xml_node<> *node = root_node_->first_node(tag1.c_str());
87 assert(node);
88 node = node->first_node(tag2.c_str());
89 while (node) {
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());
93 }
94 assert(lmax_ >= 0);
95 assert(lmax_ < 9);
96 }
97
98 // read grid
99 {
100 rapidxml::xml_node<> *node = root_node_->first_node("grid");
101
102 assert(node);
103
104 int size = value<int>(node->first_attribute("npts"));
105 grid_.resize(size);
106 std::istringstream stst(node->first_node("grid-data")->value());
107 for (int ii = 0; ii < size; ii++) {
108 stst >> grid_[ii];
109 if (ii > 0)
110 assert(grid_[ii] > grid_[ii - 1]);
111 }
112
113 assert(fabs(grid_[0]) <= 1e-10);
114
115 mesh_size_ = 0;
116 for (double rr = 0.0; rr <= grid_[grid_.size() - 1]; rr += mesh_spacing())
117 mesh_size_++;
118
119 grid_weights_.resize(grid_.size());
120
121 // the integration weights are not available, we approximate them
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]);
127 }
128 }
129
132 }
133
134 int size() const { return buffer_.size(); };
135
136 std::string description() const { return ""; }
137
139 return element::trim(spec_node_->first_attribute("atomic-label")->value());
140 }
141
142 int atomic_number() const {
143 return value<int>(spec_node_->first_attribute("atomic-number"));
144 }
145
146 double mass() const {
147 element el(symbol());
148 return el.mass();
149 }
150
151 double valence_charge() const {
152 return value<double>(spec_node_->first_node("valence-configuration")
153 ->first_attribute("total-valence-charge"));
154 }
155
156 int llocal() const { return -1; }
157
159 // PSML uses libxc ids, so we just need to read the value
160 rapidxml::xml_node<> *node = spec_node_->first_node("exchange-correlation")
161 ->first_node("libxc-info")
162 ->first_node("functional");
163 while (node) {
164 if (value<std::string>(node->first_attribute("type")) == "exchange") {
166 value<int>(node->first_attribute("id")));
167 }
168 node = node->next_sibling("functional");
169 }
171 }
172
174 // PSML uses libxc ids, so we just need to read the value
175 rapidxml::xml_node<> *node = spec_node_->first_node("exchange-correlation")
176 ->first_node("libxc-info")
177 ->first_node("functional");
178 while (node) {
179 if (value<std::string>(node->first_attribute("type")) == "correlation") {
181 value<int>(node->first_attribute("id")));
182 }
183 node = node->next_sibling("functional");
184 }
186 }
187
188 int nchannels() const {
190 return 1;
191 int nc = 0;
192 rapidxml::xml_node<> *node = root_node_->first_node("nonlocal-projectors");
193 assert(node);
194 node = node->first_node("proj");
195 while (node) {
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");
199 }
200 return nc;
201 }
202
203 void local_potential(std::vector<double> &val) const {
204 read_function(root_node_->first_node("local-potential"), val, true);
205 }
206
207 int nprojectors() const {
208 rapidxml::xml_node<> *node =
209 root_node_->first_node("nonlocal-projectors")->first_node("proj");
210 int count = 0;
211 while (node) {
212 count++;
213 node = node->next_sibling("proj");
214 }
215 return count;
216 }
217
218 int nprojectors_per_l(int l) const {
220 return 1;
221
222 rapidxml::xml_node<> *node =
223 root_node_->first_node("nonlocal-projectors")->first_node("proj");
224 int count = 0;
225 while (node) {
226 int read_l = letter_to_l(node->first_attribute("l")->value());
227 if (read_l == l) count++;
228 node = node->next_sibling("proj");
229 }
230 return count;
231 }
232
233
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");
237 while (node) {
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)
241 break;
242 node = node->next_sibling("proj");
243 }
244 read_function(node, val);
245 }
246
247 double d_ij(int l, int ic, int jc) const {
248 if (ic != jc)
249 return 0.0;
250
251 rapidxml::xml_node<> *node =
252 root_node_->first_node("nonlocal-projectors")->first_node("proj");
253 while (node) {
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)
257 break;
258 node = node->next_sibling("proj");
259 }
260 assert(node);
261 return value<double>(node->first_attribute("ekb"));
262 }
263
264 bool has_radial_function(int l) const { return false; }
265
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");
269 while (node) {
270 int read_l = letter_to_l(node->first_attribute("l")->value());
271 if (l == read_l)
272 break;
273 node = node->next_sibling("pswf");
274 }
275 read_function(node, val);
276 }
277
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");
281 while (node) {
282 int read_l = letter_to_l(node->first_attribute("l")->value());
283 if (l == read_l)
284 break;
285 node = node->next_sibling("slps");
286 }
287 read_function(node, val);
288 }
289
290 bool has_nlcc() const {
291 rapidxml::xml_node<> *node = root_node_->first_node("pseudocore-charge");
292 return node;
293 }
294
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;
299 }
300
301 bool has_density() { return root_node_->first_node("valence-charge"); }
302
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;
307 }
308
310 return spec_node_->first_attribute("relativity")->value() ==
311 std::string("dirac");
312 }
313
314 int projector_2j(int l, int ic) const {
315 rapidxml::xml_node<> *node =
316 root_node_->first_node("nonlocal-projectors")->first_node("proj");
317 while (node) {
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);
324 }
325 node = node->next_sibling("proj");
326 }
327 assert(false);
328 return 0;
329 }
330
331private:
332 void read_function(rapidxml::xml_node<> *base_node, std::vector<double> &val,
333 bool potential_padding = false) const {
334 assert(base_node);
335 rapidxml::xml_node<> *node =
336 base_node->first_node("radfunc")->first_node("data");
337 assert(node);
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++)
344 stst >> val[ii];
345
346 if (potential_padding) {
347 for (unsigned ii = size; ii < grid_.size(); ii++)
348 val[ii] = -valence_charge() / grid_[ii];
349 } else {
350 for (unsigned ii = size; ii < grid_.size(); ii++)
351 val[ii] = 0.0;
352 }
353
355 }
356
357 // for some stupid reason psml uses letters instead of numbers for angular
358 // momentum
359 static int letter_to_l(const std::string &letter) {
360 if (letter == "s")
361 return 0;
362 if (letter == "p")
363 return 1;
364 if (letter == "d")
365 return 2;
366 if (letter == "f")
367 return 3;
368 if (letter == "g")
369 return 4;
370 if (letter == "h")
371 return 5;
372 return -1;
373 }
374
375 std::ifstream file_;
376 std::vector<char> buffer_;
377 rapidxml::xml_document<> doc_;
378 rapidxml::xml_node<> *root_node_;
379 rapidxml::xml_node<> *spec_node_;
380};
381
382} // namespace pseudopotential
383
384#endif
Definition: anygrid.hpp:29
std::vector< double > grid_
Definition: anygrid.hpp:81
double mesh_spacing() const
Definition: anygrid.hpp:34
int mesh_size_
Definition: anygrid.hpp:83
std::vector< double > grid_weights_
Definition: anygrid.hpp:82
void interpolate(std::vector< double > &function) const
Definition: anygrid.hpp:61
std::string filename_
Definition: base.hpp:175
pseudopotential::type type_
Definition: base.hpp:185
int lmax_
Definition: base.hpp:186
Definition: element.hpp:34
double mass() const
Definition: element.hpp:73
static std::string trim(std::string str, const std::string &chars="\t\n\v\f\r ")
Definition: element.hpp:140
Definition: psml.hpp:36
double valence_charge() const
Definition: psml.hpp:151
std::string symbol() const
Definition: psml.hpp:138
pseudopotential::exchange exchange() const
Definition: psml.hpp:158
double mass() const
Definition: psml.hpp:146
void projector(int l, int ic, std::vector< double > &val) const
Definition: psml.hpp:234
bool has_density()
Definition: psml.hpp:301
psml(const std::string &filename, bool uniform_grid=false)
Definition: psml.hpp:39
static int letter_to_l(const std::string &letter)
Definition: psml.hpp:359
bool has_radial_function(int l) const
Definition: psml.hpp:264
void density(std::vector< double > &val) const
Definition: psml.hpp:303
std::string description() const
Definition: psml.hpp:136
rapidxml::xml_node * spec_node_
Definition: psml.hpp:379
double d_ij(int l, int ic, int jc) const
Definition: psml.hpp:247
int size() const
Definition: psml.hpp:134
pseudopotential::correlation correlation() const
Definition: psml.hpp:173
bool has_total_angular_momentum() const
Definition: psml.hpp:309
pseudopotential::format format() const
Definition: psml.hpp:130
int llocal() const
Definition: psml.hpp:156
void radial_potential(int l, std::vector< double > &val) const
Definition: psml.hpp:278
int nprojectors_per_l(int l) const
Definition: psml.hpp:218
std::ifstream file_
Definition: psml.hpp:375
bool has_nlcc() const
Definition: psml.hpp:290
int projector_2j(int l, int ic) const
Definition: psml.hpp:314
std::vector< char > buffer_
Definition: psml.hpp:376
void read_function(rapidxml::xml_node<> *base_node, std::vector< double > &val, bool potential_padding=false) const
Definition: psml.hpp:332
rapidxml::xml_node * root_node_
Definition: psml.hpp:378
int atomic_number() const
Definition: psml.hpp:142
void radial_function(int l, std::vector< double > &val) const
Definition: psml.hpp:266
void nlcc_density(std::vector< double > &val) const
Definition: psml.hpp:295
rapidxml::xml_document doc_
Definition: psml.hpp:377
void local_potential(std::vector< double > &val) const
Definition: psml.hpp:203
int nprojectors() const
Definition: psml.hpp:207
int nchannels() const
Definition: psml.hpp:188
!The assertions are ignored if the code is compiled in not debug when !prints out the assertion string
Definition: global.h:58
void const fint const fint * val
Definition: iihash_low.cc:41
Definition: anygrid.hpp:27
correlation
Definition: base.hpp:74
format
Definition: base.hpp:49
exchange
Definition: base.hpp:64
ptrdiff_t l
Definition: operate_inc.c:51