Octopus
upf2.hpp
Go to the documentation of this file.
1#ifndef PSEUDO_UPF2_HPP
2#define PSEUDO_UPF2_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 <rapidxml.hpp>
32
33#include "element.hpp"
34
35namespace pseudopotential {
36
37class upf2 : public pseudopotential::upf {
38
39public:
40 upf2(const std::string &filename, bool uniform_grid = false)
41 : pseudopotential::upf(uniform_grid), file_(filename.c_str()),
42 buffer_((std::istreambuf_iterator<char>(file_)),
43 std::istreambuf_iterator<char>()) {
44
45 filename_ = filename;
46
47 buffer_.push_back('\0');
48 doc_.parse<0>(&buffer_[0]);
49
50 root_node_ = doc_.first_node("UPF");
51
52 if (!root_node_)
53 throw status::FORMAT_NOT_SUPPORTED;
54
55 if (root_node_->first_attribute("version")->value()[0] != '2')
56 throw status::FORMAT_NOT_SUPPORTED;
57
58 std::string pseudo_type = root_node_->first_node("PP_HEADER")
59 ->first_attribute("pseudo_type")
60 ->value();
61
62 if (pseudo_type == "NC" || pseudo_type == "SL") {
63 type_ = pseudopotential::type::KLEINMAN_BYLANDER;
64 } else if (pseudo_type == "USPP") {
65 throw status::UNSUPPORTED_TYPE_ULTRASOFT;
66 } else if (pseudo_type == "PAW") {
67 throw status::UNSUPPORTED_TYPE_PAW;
68 } else {
69 throw status::UNSUPPORTED_TYPE;
70 }
71
72 assert(root_node_);
73
74 // Read the grid
75 {
76 rapidxml::xml_base<> *xmin =
77 root_node_->first_node("PP_MESH")->first_attribute("xmin");
78
79 start_point_ = 0;
80 if (xmin && fabs(value<double>(xmin)) > 1.0e-10)
81 start_point_ = 1;
82
83 rapidxml::xml_node<> *node =
84 root_node_->first_node("PP_MESH")->first_node("PP_R");
85
86 assert(node);
87
88 rapidxml::xml_attribute<> *size_attr = node->first_attribute("size");
89
90 // some files seems to have this information elsewhere
91 if (size_attr == NULL)
92 size_attr = root_node_->first_node("PP_MESH")->first_attribute("mesh");
93
94 if (size_attr == NULL)
95 throw status::FORMAT_NOT_SUPPORTED;
96
97 int size = value<int>(size_attr);
98
99 grid_.resize(size + start_point_);
100 std::istringstream stst(node->value());
101 grid_[0] = 0.0;
102 for (int ii = 0; ii < size; ii++)
103 stst >> grid_[start_point_ + ii];
104
105 assert(fabs(grid_[0]) <= 1e-10);
106 }
107
108 {
109 rapidxml::xml_node<> *node =
110 root_node_->first_node("PP_MESH")->first_node("PP_RAB");
111
112 assert(node);
113
114 int size = get_size(node);
115
116 grid_weights_.resize(size + start_point_);
117 std::istringstream stst(node->value());
118 grid_weights_[0] = 0.5 * (grid_[1] - grid_[0]);
119 for (int ii = 0; ii < size; ii++)
120 stst >> grid_weights_[start_point_ + ii];
121
122 mesh_size_ = 0;
123 for (double rr = 0.0; rr <= grid_[grid_.size() - 1]; rr += mesh_spacing())
124 mesh_size_++;
125 }
126
127 // calculate lmax (we can't trust the one given by the file :-/)
128
129 std::vector<bool> has_l(MAX_L, false);
130
131 lmax_ = 0;
132 nchannels_ = 0;
133
134 proj_l_.resize(nprojectors());
135 proj_c_.resize(nprojectors());
136
137 // projector info
138 for (int iproj = 0; iproj < nprojectors(); iproj++) {
139 std::ostringstream tag;
140 tag << "PP_BETA." << iproj + 1;
141 rapidxml::xml_node<> *node =
142 root_node_->first_node("PP_NONLOCAL")->first_node(tag.str().c_str());
143
144 assert(node);
145
146 int read_l = value<int>(node->first_attribute("angular_momentum"));
147
148 lmax_ = std::max(lmax_, read_l);
149 proj_l_[iproj] = read_l;
150 has_l[read_l] = true;
151
152 // now calculate the channel index, by counting previous projectors with
153 // the same l
154 proj_c_[iproj] = 0;
155 for (int jproj = 0; jproj < iproj; jproj++)
156 if (read_l == proj_l_[jproj])
157 proj_c_[iproj]++;
158
159 nchannels_ = std::max(nchannels_, proj_c_[iproj] + 1);
160 }
161
162 assert(lmax_ >= 0);
163
164 llocal_ = -1;
165 for (int l = 0; l <= lmax_; l++)
166 if (!has_l[l])
167 llocal_ = l;
168
169 // Read dij once
170 {
171
172 rapidxml::xml_node<> *node =
173 root_node_->first_node("PP_NONLOCAL")->first_node("PP_DIJ");
174
175 assert(node);
176
177 dij_.resize((lmax_ + 1) * nchannels_ * nchannels_);
178
179 for (unsigned kk = 0; kk < dij_.size(); kk++)
180 dij_[kk] = 0.0;
181
182 std::istringstream stst(node->value());
183 for (int ii = 0; ii < nprojectors(); ii++) {
184 for (int jj = 0; jj < nprojectors(); jj++) {
185 double val;
186 stst >> val;
187
188 if (proj_l_[ii] != proj_l_[jj]) {
189 assert(fabs(val) < 1.0e-10);
190 continue;
191 }
192
193 val *= 0.5; // convert from Rydberg to Hartree
194 d_ij(proj_l_[ii], proj_c_[ii], proj_c_[jj]) = val;
195 }
196 }
197 }
198 }
199
200 pseudopotential::format format() const {
201 return pseudopotential::format::UPF2;
202 }
203
204 int size() const { return buffer_.size(); };
205
206 std::string description() const {
207 return root_node_->first_node("PP_INFO")->value();
208 }
209
210 std::string symbol() const {
211 return element::trim(root_node_->first_node("PP_HEADER")
212 ->first_attribute("element")
213 ->value());
214 }
215
216 int atomic_number() const {
217 element el(symbol());
218 return el.atomic_number();
219 }
220
221 double mass() const {
222 element el(symbol());
223 return el.mass();
224 }
225
226 double valence_charge() const {
227 return value<double>(
228 root_node_->first_node("PP_HEADER")->first_attribute("z_valence"));
229 }
230
231 pseudopotential::exchange exchange() const {
232 std::string functional = root_node_->first_node("PP_HEADER")
233 ->first_attribute("functional")
234 ->value();
235 if (functional == "PBE")
236 return pseudopotential::exchange::PBE;
237 if (functional == "PBESOL")
238 return pseudopotential::exchange::PBE_SOL;
239 if (functional == "SLA PW NOGX NOGC")
240 return pseudopotential::exchange::LDA;
241 if (functional == "BLYP")
242 return pseudopotential::exchange::B88;
243 return pseudopotential::exchange::UNKNOWN;
244 }
245
246 pseudopotential::correlation correlation() const {
247 std::string functional = root_node_->first_node("PP_HEADER")
248 ->first_attribute("functional")
249 ->value();
250 if (functional == "PBE")
251 return pseudopotential::correlation::PBE;
252 if (functional == "PBESOL")
253 return pseudopotential::correlation::PBE_SOL;
254 if (functional == "SLA PW NOGX NOGC")
255 return pseudopotential::correlation::LDA_PW;
256 if (functional == "BLYP")
257 return pseudopotential::correlation::LYP;
258 return pseudopotential::correlation::UNKNOWN;
259 }
260
261 void local_potential(std::vector<double> &potential) const {
262 rapidxml::xml_node<> *node = root_node_->first_node("PP_LOCAL");
263
264 assert(node);
265
266 int size = get_size(node);
267
268 potential.resize(size + start_point_);
269 std::istringstream stst(node->value());
270 for (int ii = 0; ii < size; ii++) {
271 stst >> potential[ii + start_point_];
272 potential[ii + start_point_] *= 0.5; // Convert from Rydberg to Hartree
273 }
274 if (start_point_ > 0)
275 extrapolate_first_point(potential);
276
277 interpolate(potential);
278 }
279
280 int nprojectors() const {
281 return value<int>(
282 root_node_->first_node("PP_HEADER")->first_attribute("number_of_proj"));
283 }
284
285 int nprojectors_per_l(int l) const {
286
287 int nchannel = 0;
288 for (int jproj = 0; jproj < nprojectors(); jproj++)
289 if (proj_l_[jproj] == l)
290 nchannel = std::max(proj_c_[jproj]+1, nchannel);
291 return nchannel;
292 }
293
294 void projector(int l, int i, std::vector<double> &proj) const {
295 rapidxml::xml_node<> *node = NULL;
296
297 int iproj = 0;
298 while ((l != proj_l_[iproj] || i != proj_c_[iproj]) && iproj < nprojectors()) {
299 iproj++;
300 }
301 std::stringstream tag;
302 tag << "PP_BETA." << iproj+1;
303 node = root_node_->first_node("PP_NONLOCAL")->first_node(tag.str().c_str());
304
305 assert(node);
306
307 int size = get_size(node);
308
309 proj.resize(size + start_point_);
310 std::istringstream stst(node->value());
311 for (int ii = 0; ii < size; ii++)
312 stst >> proj[ii + start_point_];
313
314 // the projectors come multiplied by r, so we have to divide and fix the
315 // first point
316 for (int ii = 1; ii < size + start_point_; ii++)
317 proj[ii] /= grid_[ii];
318 extrapolate_first_point(proj);
319
320 interpolate(proj);
321 }
322
323 bool has_radial_function(int l) const { return false; }
324
325 void radial_function(int l, std::vector<double> &function) const {
326 function.clear();
327 }
328
329 void radial_potential(int l, std::vector<double> &function) const {
330 function.clear();
331 }
332
333 bool has_nlcc() const { return root_node_->first_node("PP_NLCC"); }
334
335 void nlcc_density(std::vector<double> &density) const {
336 rapidxml::xml_node<> *node = root_node_->first_node("PP_NLCC");
337 assert(node);
338
339 int size = get_size(node);
340
341 density.resize(size + start_point_);
342
343 std::istringstream stst(node->value());
344 for (int ii = 0; ii < size; ii++)
345 stst >> density[start_point_ + ii];
346 extrapolate_first_point(density);
347 // this charge does not come multiplied by anything
348
349 interpolate(density);
350 }
351
352 bool has_total_angular_momentum() const {
353 return root_node_->first_node("PP_SPIN_ORB");
354 }
355
356 void beta(int iproj, int &l, std::vector<double> &proj) const {
357 rapidxml::xml_node<> *node = NULL;
358
359 std::stringstream tag;
360 tag << "PP_BETA." << iproj + 1;
361 node = root_node_->first_node("PP_NONLOCAL")->first_node(tag.str().c_str());
362
363 assert(node);
364
365 l = value<int>(node->first_attribute("angular_momentum"));
366
367 int size = get_size(node);
368
369 proj.resize(size + start_point_);
370 std::istringstream stst(node->value());
371 for (int ii = 0; ii < size; ii++)
372 stst >> proj[ii + start_point_];
373
374 // the projectors come multiplied by r, so we have to divide and fix the
375 // first point
376 for (int ii = 1; ii < size + start_point_; ii++)
377 proj[ii] /= grid_[ii];
378 extrapolate_first_point(proj);
379
380 interpolate(proj);
381 }
382
383 void dnm_zero(int nbeta, std::vector<std::vector<double>> &dnm) const {
384 dnm.resize(nbeta);
385 for (int i = 0; i < nbeta; i++) {
386 dnm[i].resize(nbeta);
387 for (int j = 0; j < nbeta; j++) {
388 dnm[i][j] = dij_[i * nbeta + j];
389 }
390 }
391 }
392
393 bool has_density() const { return root_node_->first_node("PP_RHOATOM"); }
394
395 void density(std::vector<double> &val) const {
396 rapidxml::xml_node<> *node = root_node_->first_node("PP_RHOATOM");
397 assert(node);
398
399 int size = get_size(node);
400
401 val.resize(size + start_point_);
402
403 std::istringstream stst(node->value());
404 for (int ii = 0; ii < size; ii++)
405 stst >> val[start_point_ + ii];
406
407 // the density comes multiplied by 4\pi r
408 for (int ii = 1; ii < size + start_point_; ii++)
409 val[ii] /= 4.0 * M_PI * grid_[ii] * grid_[ii];
410 extrapolate_first_point(val);
411
412 interpolate(val);
413 }
414
415 int nwavefunctions() const {
416 return value<int>(
417 root_node_->first_node("PP_HEADER")->first_attribute("number_of_wfc"));
418 }
419
420 void wavefunction(int index, int &n, int &l, double &occ,
421 std::vector<double> &proj) const {
422 rapidxml::xml_node<> *node = NULL;
423
424 std::stringstream tag;
425 tag << "PP_CHI." << index + 1;
426 node = root_node_->first_node("PP_PSWFC")->first_node(tag.str().c_str());
427
428 assert(node);
429
430 // not all files have "n", so we might have to parse the label
431 if (node->first_attribute("n")) {
432 n = value<int>(node->first_attribute("n"));
433 } else {
434 std::string label = node->first_attribute("label")->value();
435 n = atoi(label.substr(0, 1).c_str());
436 }
437
438 l = value<int>(node->first_attribute("l"));
439
440 occ = value<double>(node->first_attribute("occupation"));
441
442 int size = get_size(node);
443
444 proj.resize(size + start_point_);
445 std::istringstream stst(node->value());
446 for (int ii = 0; ii < size; ii++)
447 stst >> proj[ii + start_point_];
448
449 // the wavefunctions come multiplied by r, so we have to divide and fix the
450 // first point
451 for (int ii = 1; ii < size + start_point_; ii++)
452 proj[ii] /= grid_[ii];
453 extrapolate_first_point(proj);
454
455 interpolate(proj);
456 }
457
458 // Retreive the value of 2*j for relativistic projectors
459 int projector_2j(int l, int ic) const {
460
461 if (l == 0)
462 return 1;
463
464 for (int iproj = 0; iproj < nprojectors(); iproj++) {
465 std::stringstream tag;
466 tag << "PP_RELBETA." << iproj + 1;
467
468 rapidxml::xml_node<> *node =
469 root_node_->first_node("PP_SPIN_ORB")->first_node(tag.str().c_str());
470 assert(node);
471
472 std::string labell = node->first_attribute("lll")->value();
473 if(atoi(labell.c_str()) == l && proj_c_[iproj] == ic){
474 std::string labelj = node->first_attribute("jjj")->value();
475 float j = atof(labelj.c_str());
476
477 return lrint(j * 2.0);
478 }
479 }
480
481 return -1;
482 }
483
484
485 // Retreive the value of 2*j for relativitstic wavefunctions
486 int wavefunction_2j(int ii) const {
487
488 std::stringstream tag;
489 tag << "PP_RELWFC." << ii;
490
491 rapidxml::xml_node<> *node =
492 root_node_->first_node("PP_SPIN_ORB")->first_node(tag.str().c_str());
493 assert(node);
494
495 std::string label = node->first_attribute("jchi")->value();
496 float j = atof(label.c_str());
497
498 return lrint(j * 2.0);
499 }
500
501
502private:
503 int get_size(const rapidxml::xml_node<> *node) const {
504 int size = grid_.size() - start_point_;
505
506 rapidxml::xml_attribute<> *size_attr = node->first_attribute("size");
507
508 if (size_attr != NULL)
509 size = value<int>(size_attr);
510
511 return size;
512 }
513
514 std::ifstream file_;
515 std::vector<char> buffer_;
516 rapidxml::xml_document<> doc_;
517 rapidxml::xml_node<> *root_node_;
518 std::vector<int> proj_l_;
519 std::vector<int> proj_c_;
520};
521
522} // namespace pseudopotential
523
524#endif
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
Definition: global.h:46
double fabs(double __x) __attribute__((__nothrow__
integer, parameter, public density
Definition: quantity.F90:146
integer, parameter, public mass
Definition: quantity.F90:146
ptrdiff_t l
Definition: operate_inc.c:12
ptrdiff_t i
Definition: operate_inc.c:12
ptrdiff_t j
Definition: operate_inc.c:12
const int *restrict index
Definition: operate_inc.c:13