Octopus
psp8.hpp
Go to the documentation of this file.
1#ifndef PSEUDO_PSP8_HPP
2#define PSEUDO_PSP8_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 "element.hpp"
31
32namespace pseudopotential {
33
34class psp8 : public pseudopotential::base {
35
36public:
37 psp8(const std::string &filename) {
38
39 filename_ = filename;
40
41 std::ifstream original_file(filename.c_str());
42 std::string buffer((std::istreambuf_iterator<char>(original_file)),
43 std::istreambuf_iterator<char>());
44 std::replace(buffer.begin(), buffer.end(), 'D', 'E');
45 std::replace(buffer.begin(), buffer.end(), 'd', 'e');
46
47 std::istringstream file(buffer);
48
49 type_ = pseudopotential::type::KLEINMAN_BYLANDER;
50
51 // file size
52 file.seekg(0, std::ios::beg);
53 std::streampos file_size_ = file.tellg();
54 file.seekg(0, std::ios::end);
55 file_size_ = file.tellg() - file_size_;
56
57 // parse the header
58 file.seekg(0, std::ios::beg);
59 std::string line;
60
61 // line 1
62 getline(file, description_);
63
64 // line 2
65 double val;
66 file >> val;
67 atomic_number_ = round(val);
68 file >> valence_charge_;
69 getline(file, line);
70
71 // line 3
72 int pspcod = -1;
73 file >> pspcod >> ixc_ >> lmax_ >> llocal_ >> mesh_size_;
74 if (pspcod != 8)
75 throw status::UNKNOWN_FORMAT;
76 getline(file, line);
77
78 // line 4
79 file >> val;
80 file >> val;
81 nlcc_ = (val > 0.0);
82 getline(file, line);
83
84 // line 5
85 nprojectors_ = 0;
86 nchannels_ = 0;
87 for (int l = 0; l <= lmax_; l++) {
88 int np;
89 file >> np;
90 nprojl_.push_back(np);
91 nprojectors_ += np;
92 nchannels_ = std::max(nchannels_, np);
93 }
94 getline(file, line);
95
96 // line 6
97 int extension_switch;
98 file >> extension_switch;
99 getline(file, line);
100 has_density_ = extension_switch == 1;
101 has_soc_ = extension_switch == 2;
102
103 // there is an extra line for spin orbit stuff
104 if (has_soc_)
105 getline(file, line);
106
107 if (extension_switch > 2)
108 throw status::FORMAT_NOT_SUPPORTED;
109
110 // the projectors and local potential
111 projectors_.resize(lmax_ + 1);
112 ekb_.resize(lmax_ + 1);
113 for (int l = 0; l <= lmax_; l++) {
114 projectors_[l].resize(nprojl_[l]);
115 ekb_[l].resize(nprojl_[l]);
116
117 if (l == llocal_) {
118 read_local_potential(file);
119 continue;
120 }
121
122 if (nprojl_[l] == 0)
123 continue;
124
125 int read_l;
126 file >> read_l;
127
128 assert(read_l == l);
129
130 for (int iproj = 0; iproj < nprojl_[l]; iproj++) {
131 projectors_[l][iproj].resize(mesh_size_);
132 file >> ekb_[l][iproj];
133 }
134 getline(file, line);
135
136 for (int ip = 0; ip < mesh_size_; ip++) {
137 int read_ip;
138 double grid_point;
139 file >> read_ip >> grid_point;
140
141 assert(read_ip == ip + 1);
142
143 for (int iproj = 0; iproj < nprojl_[l]; iproj++)
144 file >> projectors_[l][iproj][ip];
145 getline(file, line);
146 }
147 }
148
149 // the local potential if it was not read before
150 if (llocal_ > lmax_)
151 read_local_potential(file);
152
153 // NLCC
154 if (nlcc_) {
155 nlcc_density_.resize(mesh_size_);
156
157 for (int ip = 0; ip < mesh_size_; ip++) {
158 int read_ip;
159 double grid_point;
160 file >> read_ip >> grid_point >> nlcc_density_[ip];
161 assert(read_ip == ip + 1);
162 getline(file, line);
163 }
164 }
165
166 if (extension_switch == 1) {
167
168 density_.resize(mesh_size_);
169
170 for (int ip = 0; ip < mesh_size_; ip++) {
171 int read_ip;
172 double grid_point;
173 file >> read_ip >> grid_point >> density_[ip];
174 assert(read_ip == ip + 1);
175 getline(file, line);
176 }
177 }
178 }
179
180 pseudopotential::format format() const {
181 return pseudopotential::format::PSP8;
182 }
183
184 int size() const { return file_size_; };
185
186 std::string description() const { return description_; }
187
188 std::string symbol() const {
189 pseudopotential::element el(atomic_number_);
190 return el.symbol();
191 }
192
193 int atomic_number() const { return atomic_number_; }
194
195 double mass() const {
196 pseudopotential::element el(atomic_number_);
197 return el.mass();
198 }
199
200 double valence_charge() const { return valence_charge_; }
201
202 pseudopotential::exchange exchange() const {
203 if (ixc_ > 0) {
204 if (ixc_ == 1)
205 return pseudopotential::exchange::NONE;
206 if (ixc_ >= 2 && ixc_ <= 9)
207 return pseudopotential::exchange::LDA;
208 if (ixc_ == 11 || ixc_ == 12)
209 return pseudopotential::exchange::PBE;
210 } else {
211 return pseudopotential::exchange((-ixc_ + ixc_ % 1000) / 1000);
212 }
213
214 return pseudopotential::exchange::UNKNOWN;
215 }
216
217 pseudopotential::correlation correlation() const {
218 if (ixc_ > 0) {
219 if (ixc_ == 1)
220 return pseudopotential::correlation::LDA_XC_TETER93;
221 if (ixc_ == 2)
222 return pseudopotential::correlation::LDA_PZ;
223 if (ixc_ == 7)
224 return pseudopotential::correlation::LDA_PW;
225 if (ixc_ == 7 || ixc_ == 8)
226 return pseudopotential::correlation::NONE;
227 if (ixc_ == 11)
228 return pseudopotential::correlation::PBE;
229 if (ixc_ == 12)
230 return pseudopotential::correlation::NONE;
231 } else {
232 return pseudopotential::correlation(-ixc_ % 1000);
233 }
234
235 return pseudopotential::correlation::UNKNOWN;
236 }
237
238 int llocal() const {
239 if (llocal_ > lmax_)
240 return -1;
241 return llocal_;
242 }
243
244 int nchannels() const { return nchannels_; }
245
246 double mesh_spacing() const { return mesh_spacing_; }
247
248 int mesh_size() const { return mesh_size_; }
249
250 void local_potential(std::vector<double> &potential) const {
251 potential.resize(mesh_size_);
252 assert(mesh_size_ == local_potential_.size());
253 for (int ip = 0; ip < mesh_size_; ip++)
254 potential[ip] = local_potential_[ip];
255 }
256
257 int nprojectors() const { return nprojectors_; }
258
259 int nprojectors_per_l(int l) const {
260 return nprojl_[l];
261 }
262
263 void projector(int l, int i, std::vector<double> &proj) const {
264 proj.clear();
265
266 if (l > lmax_)
267 return;
268 if (i >= nprojl_[l])
269 return;
270
271 proj.resize(mesh_size_);
272 assert(mesh_size_ == projectors_[l][i].size());
273
274 for (int ip = 1; ip < mesh_size_; ip++)
275 proj[ip] = projectors_[l][i][ip] / (mesh_spacing() * ip);
276
277 extrapolate_first_point(proj);
278 }
279
280 double d_ij(int l, int i, int j) const {
281 if (i != j)
282 return 0.0;
283 if (i >= nprojl_[l])
284 return 0.0;
285 return ekb_[l][i];
286 }
287
288 bool has_radial_function(int l) const { return false; }
289
290 void radial_function(int l, std::vector<double> &function) const {
291 function.clear();
292 }
293
294 void radial_potential(int l, std::vector<double> &function) const {
295 function.clear();
296 }
297
298 bool has_nlcc() const { return nlcc_; }
299
300 bool has_total_angular_momentum() const { return has_soc_; }
301
302 void nlcc_density(std::vector<double> &density) const {
303 density.resize(mesh_size_);
304 assert(mesh_size_ == nlcc_density_.size());
305 for (int ip = 0; ip < mesh_size_; ip++)
306 density[ip] = nlcc_density_[ip] / (4.0 * M_PI);
307 }
308
309 bool has_density() const { return has_density_; }
310
311 void density(std::vector<double> &density) const {
312 density.resize(mesh_size_);
313 assert(mesh_size_ == density_.size());
314 for (int ip = 0; ip < mesh_size_; ip++)
315 density[ip] = density_[ip] / (4.0 * M_PI);
316 }
317
318private:
319 void extrapolate_first_point(std::vector<double> &function_) const {
320
321 assert(function_.size() >= 4);
322
323 double x1 = mesh_spacing();
324 double x2 = 2 * mesh_spacing();
325 double x3 = 3 * mesh_spacing();
326 double f1 = function_[1];
327 double f2 = function_[2];
328 double f3 = function_[3];
329
330 // obtained from:
331 // http://www.wolframalpha.com/input/?i=solve+%7Bb*x1%5E2+%2B+c*x1+%2B+d+%3D%3D+f1,++b*x2%5E2+%2B+c*x2+%2B+d+%3D%3D+f2,+b*x3%5E2+%2B+c*x3+%2B+d+%3D%3D+f3+%7D++for+b,+c,+d
332
333 function_[0] = f1 * x2 * x3 * (x2 - x3) + f2 * x1 * x3 * (x3 - x1) +
334 f3 * x1 * x2 * (x1 - x2);
335 function_[0] /= (x1 - x2) * (x1 - x3) * (x2 - x3);
336 }
337
338 void read_local_potential(std::istream &file) {
339 int read_llocal;
340 std::string line;
341
342 file >> read_llocal;
343
344 assert(llocal_ == read_llocal);
345 getline(file, line);
346
347 local_potential_.resize(mesh_size_);
348 for (int ip = 0; ip < mesh_size_; ip++) {
349 int read_ip;
350 double grid_point;
351 file >> read_ip >> grid_point >> local_potential_[ip];
352 assert(read_ip == ip + 1);
353 getline(file, line);
354
355 if (ip == 1) {
356 mesh_spacing_ = grid_point;
357 }
358 }
359 }
360
361 size_t file_size_;
362 std::string description_;
363 int atomic_number_;
364 double valence_charge_;
365 int ixc_;
366 int llocal_;
367 int mesh_size_;
368 int nchannels_;
369 double mesh_spacing_;
370 std::vector<int> nprojl_;
371 int nprojectors_;
372 std::vector<std::vector<std::vector<double>>> projectors_;
373 std::vector<std::vector<double>> ekb_;
374 std::vector<double> local_potential_;
375 bool nlcc_;
376 std::vector<double> nlcc_density_;
377 bool has_density_;
378 std::vector<double> density_;
379 bool has_soc_;
380};
381
382} // namespace pseudopotential
383
384#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 the file
Definition: global.h:46
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
real(real64) f3
Definition: pcm_eom.F90:200
real(real64) f2
Definition: pcm_eom.F90:200
real(real64) f1
Definition: pcm_eom.F90:200
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