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