Octopus
qso.hpp
Go to the documentation of this file.
1#ifndef PSEUDO_QSO_HPP
2#define PSEUDO_QSO_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 <fstream>
24#include <iostream>
25#include <sstream>
26#include <vector>
27
28#include "base.hpp"
29#include "element.hpp"
30
31#include <rapidxml.hpp>
32
33namespace pseudopotential {
34
35class qso : public pseudopotential::base {
36
37public:
38 qso(const std::string &filename)
39 : file_(filename.c_str()),
40 buffer_((std::istreambuf_iterator<char>(file_)),
41 std::istreambuf_iterator<char>()) {
42
43 filename_ = filename;
44
45 buffer_.push_back('\0');
46 doc_.parse<0>(&buffer_[0]);
47
48 root_node_ = doc_.first_node("fpmd:species");
49 // for the old version of the standard
50 if (!root_node_)
51 root_node_ = doc_.first_node("qbox:species");
52 if (!root_node_)
53 throw status::FORMAT_NOT_SUPPORTED;
54
55 pseudo_node_ = root_node_->first_node("ultrasoft_pseudopotential");
56 if (pseudo_node_)
57 type_ = pseudopotential::type::ULTRASOFT;
58
59 if (!pseudo_node_) {
60 pseudo_node_ =
61 root_node_->first_node("norm_conserving_semilocal_pseudopotential");
62 if (pseudo_node_)
63 type_ = pseudopotential::type::KLEINMAN_BYLANDER;
64 }
65
66 if (!pseudo_node_) {
67 pseudo_node_ = root_node_->first_node("norm_conserving_pseudopotential");
68 if (pseudo_node_)
69 type_ = pseudopotential::type::SEMILOCAL;
70 }
71
72 assert(pseudo_node_);
73
74 // read lmax
75 lmax_ = -1;
76 if (pseudo_node_->first_node("lmax")) {
77 lmax_ = value<int>(pseudo_node_->first_node("lmax"));
78 } else {
79 for (int l = 0; l <= MAX_L; l++) {
80 if (!has_projectors(l)) {
81 lmax_ = l - 1;
82 break;
83 }
84 }
85 }
86 assert(lmax_ >= 0);
87 assert(lmax_ < MAX_L);
88 }
89
90 pseudopotential::format format() const {
91 return pseudopotential::format::QSO;
92 }
93
94 int size() const { return buffer_.size(); };
95
96 std::string description() const {
97 return root_node_->first_node("description")->value();
98 }
99
100 std::string symbol() const {
101 return element::trim(root_node_->first_node("symbol")->value());
102 }
103
104 int atomic_number() const {
105 return value<int>(root_node_->first_node("atomic_number"));
106 }
107
108 double mass() const { return value<double>(root_node_->first_node("mass")); }
109
110 double valence_charge() const {
111 return value<double>(pseudo_node_->first_node("valence_charge"));
112 }
113
114 int llocal() const {
115 if (pseudo_node_->first_node("llocal")) {
116 return value<int>(pseudo_node_->first_node("llocal"));
117 } else {
118 return -1;
119 }
120 }
121
122 int nchannels() const {
123 if (type_ == pseudopotential::type::ULTRASOFT) {
124 int np = nbeta();
125 int nl = lmax() + 1;
126 assert(np % nl == 0);
127 return np / nl;
128 }
129 if (type_ == pseudopotential::type::KLEINMAN_BYLANDER)
130 return 2;
131 return 1;
132 }
133
134 int nquad() const { return value<int>(pseudo_node_->first_node("nquad")); }
135
136 double rquad() const {
137 return value<double>(pseudo_node_->first_node("rquad"));
138 }
139
140 double mesh_spacing() const {
141 return value<double>(pseudo_node_->first_node("mesh_spacing"));
142 }
143
144 int mesh_size() const {
145 rapidxml::xml_node<> *node =
146 pseudo_node_->first_node("local_potential"); // kleinman bylander
147 if (!node)
148 node = pseudo_node_->first_node("vlocal"); // ultrasoft
149 if (!node)
150 node = pseudo_node_->first_node("projector"); // norm conserving
151 assert(node);
152 return value<int>(node->first_attribute("size"));
153 }
154
155 void local_potential(std::vector<double> &potential) const {
156 rapidxml::xml_node<> *node = pseudo_node_->first_node("local_potential");
157 if (!node) {
158 // for ultrasoft, this is called vlocal
159 node = pseudo_node_->first_node("vlocal");
160 }
161 assert(node);
162 int size = value<int>(node->first_attribute("size"));
163 potential.resize(size);
164 std::istringstream stst(node->value());
165 for (int ii = 0; ii < size; ii++) {
166 stst >> potential[ii];
167 }
168 }
169
170 int nprojectors() const {
171 switch (type_) {
172 case pseudopotential::type::ULTRASOFT:
173 return nbeta();
174 case pseudopotential::type::KLEINMAN_BYLANDER: {
175 int count = 0;
176 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
177 while (node) {
178 count++;
179 node = node->next_sibling("projector");
180 }
181 return count;
182 }
183 case pseudopotential::type::SEMILOCAL:
184 return 0;
185 }
186 return 0;
187 }
188
189 int nprojectors_per_l(int l) const {
190 switch (type_) {
191 case pseudopotential::type::ULTRASOFT:
192 return nbeta() / ( lmax() + 1);
193 case pseudopotential::type::KLEINMAN_BYLANDER: {
194 int count = 0;
195 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
196
197 while (node) {
198 int read_l = value<int>(node->first_attribute("l"));
199 if (l == read_l)
200 count++;
201 node = node->next_sibling("projector");
202 }
203 return count++;
204 }
205 case pseudopotential::type::SEMILOCAL: {
206 int count = 0;
207 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
208
209 while (node) {
210 int read_l = value<int>(node->first_attribute("l"));
211 if (l == read_l)
212 count++;
213 node = node->next_sibling("projector");
214 }
215 return count++;
216 }
217 }
218
219 return 0;
220 }
221
222
223 void projector(int l, int i, std::vector<double> &proj) const {
224
225 std::string tag = "projector";
226
227 rapidxml::xml_node<> *node = pseudo_node_->first_node(tag.c_str());
228
229 while (node) {
230 int read_l = value<int>(node->first_attribute("l"));
231 int read_i = value<int>(node->first_attribute("i")) - 1;
232 if (l == read_l && i == read_i)
233 break;
234 node = node->next_sibling(tag.c_str());
235 }
236
237 assert(node != NULL);
238
239 int size = value<int>(node->first_attribute("size"));
240 proj.resize(size);
241 std::istringstream stst(node->value());
242 for (int ii = 0; ii < size; ii++)
243 stst >> proj[ii];
244 }
245
246 double d_ij(int l, int i, int j) const {
247 rapidxml::xml_node<> *node = pseudo_node_->first_node("d_ij");
248
249 while (node) {
250 int read_l = value<int>(node->first_attribute("l"));
251 int read_i = value<int>(node->first_attribute("i")) - 1;
252 int read_j = value<int>(node->first_attribute("j")) - 1;
253 if (l == read_l && i == read_i && j == read_j)
254 break;
255 node = node->next_sibling("d_ij");
256 }
257
258 assert(node != NULL);
259
260 return value<double>(node);
261 }
262
263 bool has_radial_function(int l) const {
264 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
265
266 while (node) {
267 int read_l = value<int>(node->first_attribute("l"));
268 if (l == read_l)
269 break;
270 node = node->next_sibling("projector");
271 }
272
273 return node->first_node("radial_function") != NULL;
274 }
275
276 void radial_function(int l, std::vector<double> &function) const {
277 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
278
279 while (node) {
280 int read_l = value<int>(node->first_attribute("l"));
281 if (l == read_l)
282 break;
283 node = node->next_sibling("projector");
284 }
285
286 assert(node != NULL);
287 assert(node->first_node("radial_function"));
288
289 int size = value<int>(node->first_attribute("size"));
290 function.resize(size);
291 std::istringstream stst(node->first_node("radial_function")->value());
292 for (int ii = 0; ii < size; ii++) {
293 stst >> function[ii];
294 }
295 }
296
297 void radial_potential(int l, std::vector<double> &function) const {
298 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
299
300 while (node) {
301 int read_l = value<int>(node->first_attribute("l"));
302 if (l == read_l)
303 break;
304 node = node->next_sibling("projector");
305 }
306
307 assert(node != NULL);
308 assert(node->first_node("radial_potential"));
309
310 int size = value<int>(node->first_attribute("size"));
311 function.resize(size);
312 std::istringstream stst(node->first_node("radial_potential")->value());
313 for (int ii = 0; ii < size; ii++) {
314 stst >> function[ii];
315 }
316 }
317
318 bool has_nlcc() const { return pseudo_node_->first_node("rho_nlcc"); }
319
320 void nlcc_density(std::vector<double> &density) const {
321 rapidxml::xml_node<> *node = pseudo_node_->first_node("rho_nlcc");
322 assert(node);
323 int size = value<int>(node->first_attribute("size"));
324 density.resize(size);
325 std::istringstream stst(node->value());
326 for (int ii = 0; ii < size; ii++) {
327 stst >> density[ii];
328 }
329 }
330
331 void beta(int index, int &l, std::vector<double> &proj) const {
332 rapidxml::xml_node<> *node = pseudo_node_->first_node("beta");
333
334 for (int i = 0; i < index; i++)
335 node = node->next_sibling("beta");
336
337 assert(node != NULL);
338
339 l = value<int>(node->first_attribute("l"));
340 int size = value<int>(node->first_attribute("size"));
341 proj.resize(size);
342 std::istringstream stst(node->value());
343 for (int ii = 0; ii < size; ii++) {
344 stst >> proj[ii];
345 }
346 }
347
348 void dnm_zero(int nbeta, std::vector<std::vector<double>> &dnm) const {
349 rapidxml::xml_node<> *node = pseudo_node_->first_node("dnm_zero");
350 std::istringstream stst(node->value());
351
352 dnm.resize(nbeta);
353 for (int i = 0; i < nbeta; i++) {
354 dnm[i].resize(nbeta);
355 for (int j = 0; j < nbeta; j++) {
356 stst >> dnm[i][j];
357 }
358 }
359 }
360
361 bool has_rinner() const {
362 rapidxml::xml_node<> *node = pseudo_node_->first_node("rinner");
363 return node;
364 }
365
366 void rinner(std::vector<double> &val) const {
367 rapidxml::xml_node<> *node = pseudo_node_->first_node("rinner");
368
369 assert(node != NULL);
370
371 int size = value<int>(node->first_attribute("size"));
372 val.resize(size);
373 std::istringstream stst(node->value());
374 for (int ii = 0; ii < size; ii++) {
375 stst >> val[ii];
376 }
377 }
378
379 void qnm(int index, int &l1, int &l2, int &n, int &m,
380 std::vector<double> &val) const {
381 rapidxml::xml_node<> *node = pseudo_node_->first_node("qnm");
382
383 for (int i = 0; i < index; i++)
384 node = node->next_sibling("qnm");
385
386 assert(node != NULL);
387
388 n = value<int>(node->first_attribute("n"));
389 m = value<int>(node->first_attribute("m"));
390 l1 = value<int>(node->first_attribute("l1"));
391 l2 = value<int>(node->first_attribute("l2"));
392
393 int size = value<int>(node->first_attribute("size"));
394 val.resize(size);
395 std::istringstream stst(node->value());
396 for (int ii = 0; ii < size; ii++) {
397 stst >> val[ii];
398 }
399 }
400
401 void qfcoeff(int index, int ltot, std::vector<double> &val) const {
402 rapidxml::xml_node<> *node = pseudo_node_->first_node("qfcoeff");
403
404 while (node) {
405 int read_index = value<int>(node->first_attribute("i"));
406 int read_ltot = value<int>(node->first_attribute("ltot"));
407 if (read_index == index && read_ltot == ltot)
408 break;
409 node = node->next_sibling("qfcoeff");
410 }
411
412 assert(node != NULL);
413
414 int size = value<int>(node->first_attribute("size"));
415 val.resize(size);
416 std::istringstream stst(node->value());
417 for (int ii = 0; ii < size; ii++) {
418 stst >> val[ii];
419 }
420 }
421
422private:
423 bool has_projectors(int l) const {
424 rapidxml::xml_node<> *node = pseudo_node_->first_node("projector");
425 while (node) {
426 int read_l = value<int>(node->first_attribute("l"));
427 if (l == read_l)
428 break;
429 node = node->next_sibling("projector");
430 }
431 return node != NULL;
432 }
433
434 int nbeta() const { return value<int>(pseudo_node_->first_node("nbeta")); }
435
436 std::ifstream file_;
437 std::vector<char> buffer_;
438 rapidxml::xml_document<> doc_;
439 rapidxml::xml_node<> *root_node_;
440 rapidxml::xml_node<> *pseudo_node_;
441};
442
443} // namespace pseudopotential
444
445#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
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