1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14
15
16 #include "ECPComponentBuilder.h"
17 #include "Numerics/GaussianTimesRN.h"
18 #include "Numerics/Quadrature.h"
19 #include "QMCHamiltonians/NonLocalECPComponent.h"
20 #include "Numerics/Transform2GridFunctor.h"
21 #include "Utilities/IteratorUtility.h"
22 #include "Utilities/SimpleParser.h"
23 #include "Message/CommOperators.h"
24 #include <cmath>
25 #include "Utilities/qmc_common.h"
26
27
28 namespace qmcplusplus
29 {
ECPComponentBuilder(const std::string & aname,Communicate * c,int nrule)30 ECPComponentBuilder::ECPComponentBuilder(const std::string& aname, Communicate* c, int nrule)
31 : MPIObjectBase(c),
32 NumNonLocal(0),
33 Lmax(0),
34 Nrule(nrule),
35 Srule(8),
36 AtomicNumber(0),
37 Zeff(0),
38 RcutMax(-1),
39 Species(aname),
40 grid_global(0)
41 {
42 angMon["s"] = 0;
43 angMon["p"] = 1;
44 angMon["d"] = 2;
45 angMon["f"] = 3;
46 angMon["g"] = 4;
47 angMon["h"] = 5;
48 angMon["i"] = 6;
49 angMon["j"] = 7;
50 angMon["k"] = 8;
51 angMon["0"] = 0;
52 angMon["1"] = 1;
53 angMon["2"] = 2;
54 angMon["3"] = 3;
55 angMon["4"] = 4;
56 angMon["5"] = 5;
57 angMon["6"] = 6;
58 angMon["7"] = 7;
59 angMon["8"] = 8;
60 }
61
parse(const std::string & fname,xmlNodePtr cur)62 bool ECPComponentBuilder::parse(const std::string& fname, xmlNodePtr cur)
63 {
64 const XMLAttrString cutoff_str(cur, "cutoff");
65 if (!cutoff_str.empty())
66 RcutMax = std::stod(cutoff_str);
67
68 return read_pp_file(fname);
69 }
70
get_file_length(std::ifstream * f) const71 int ReadFileBuffer::get_file_length(std::ifstream* f) const
72 {
73 f->seekg(0, std::ios::end);
74 int len = f->tellg();
75 f->seekg(0, std::ios::beg);
76 return len;
77 }
78
reset()79 void ReadFileBuffer::reset()
80 {
81 if (is_open)
82 {
83 if (myComm == NULL || myComm->rank() == 0)
84 {
85 delete fin;
86 fin = NULL;
87 }
88 delete[] cbuffer;
89 cbuffer = NULL;
90 is_open = false;
91 length = 0;
92 }
93 }
94
open_file(const std::string & fname)95 bool ReadFileBuffer::open_file(const std::string& fname)
96 {
97 reset();
98
99 if (myComm == NULL || myComm->rank() == 0)
100 {
101 fin = new std::ifstream(fname.c_str());
102 if (fin->is_open())
103 is_open = true;
104 }
105 if (myComm)
106 myComm->bcast(is_open);
107 return is_open;
108 }
109
read_contents()110 bool ReadFileBuffer::read_contents()
111 {
112 if (!is_open)
113 return false;
114
115 if (myComm == NULL || myComm->rank() == 0)
116 {
117 length = get_file_length(fin);
118 }
119 if (myComm)
120 myComm->bcast(length);
121
122 cbuffer = new char[length + 1];
123 cbuffer[length] = '\0';
124
125 if (myComm == NULL || myComm->rank() == 0)
126 fin->read(cbuffer, length);
127
128 if (myComm != NULL)
129 myComm->bcast(cbuffer, length);
130
131 return true;
132 }
133
134
read_pp_file(const std::string & fname)135 bool ECPComponentBuilder::read_pp_file(const std::string& fname)
136 {
137 ReadFileBuffer buf(myComm);
138 bool okay = buf.open_file(fname);
139 if (!okay)
140 myComm->barrier_and_abort("ECPComponentBuilder::read_pp_file Missing PP file " + fname + "\n");
141
142 okay = buf.read_contents();
143 if (!okay)
144 myComm->barrier_and_abort("ECPComponentBuilder::read_pp_file Unable to read PP file " + fname + "\n");
145
146 xmlDocPtr m_doc = xmlReadMemory(buf.contents(), buf.length, NULL, NULL, 0);
147
148 if (m_doc == NULL)
149 {
150 xmlFreeDoc(m_doc);
151 myComm->barrier_and_abort("ECPComponentBuilder::read_pp_file xml file " + fname + " is invalid");
152 }
153 // Check the document is of the right kind
154 xmlNodePtr cur = xmlDocGetRootElement(m_doc);
155 if (cur == NULL)
156 {
157 xmlFreeDoc(m_doc);
158 myComm->barrier_and_abort("Empty document");
159 }
160 bool success = put(cur);
161 xmlFreeDoc(m_doc);
162 return success;
163 }
164
put(xmlNodePtr cur)165 bool ECPComponentBuilder::put(xmlNodePtr cur)
166 {
167 // int nk=0;
168 //vector<RealType> kpts;
169 std::vector<xmlNodePtr> semiPtr;
170 cur = cur->children;
171 while (cur != NULL)
172 {
173 std::string cname((const char*)cur->name);
174 if (cname == "header")
175 {
176 Zeff = std::stoi(XMLAttrString{cur, "zval"});
177 AtomicNumber = std::stoi(XMLAttrString{cur, "atomic-number"});
178 }
179 else if (cname == "grid")
180 {
181 //capture the global grid
182 grid_global = createGrid(cur);
183 }
184 else if (cname == "L2")
185 {
186 buildL2(cur);
187 }
188 else if (cname == "semilocal")
189 {
190 semiPtr.push_back(cur); //save the pointer
191 }
192 else if (cname == "local")
193 {
194 buildLocal(cur);
195 }
196 cur = cur->next;
197 }
198 if (semiPtr.size())
199 {
200 if (!pp_nonloc)
201 pp_nonloc = std::make_unique<NonLocalECPComponent>();
202 if (pp_so == 0)
203 pp_so = std::make_unique<SOECPComponent>();
204 if (pp_loc)
205 {
206 for (int i = 0; i < semiPtr.size(); i++)
207 addSemiLocal(semiPtr[i]);
208 }
209 else
210 buildSemiLocalAndLocal(semiPtr);
211 }
212 if (pp_nonloc)
213 {
214 SetQuadratureRule(Nrule);
215 app_log() << " Non-local pseudopotential parameters" << std::endl;
216 pp_nonloc->print(app_log());
217 app_log() << " Maximum cutoff radius " << pp_nonloc->Rmax << std::endl;
218 }
219 return true;
220 }
221
printECPTable()222 void ECPComponentBuilder::printECPTable()
223 {
224 if (!qmc_common.io_node || qmc_common.mpi_groups > 1)
225 return;
226
227 char fname[12];
228 sprintf(fname, "%s.pp.dat", Species.c_str());
229 std::ofstream fout(fname);
230 fout.setf(std::ios::scientific, std::ios::floatfield);
231 fout.precision(12);
232 int nl = pp_nonloc ? pp_nonloc->nlpp_m.size() : 0;
233 RealType d = 1.7e-2;
234 RealType rt = 0.13 * d;
235 if (nl)
236 {
237 fout << "# Lmax = " << Lmax + 1 << " nonlocal L channels" << nl << std::endl;
238 fout << "# Units = bohr hartree " << std::endl;
239 fout << "# r -r*V/zeff Vnl ... " << std::endl;
240 while (rt < 5)
241 {
242 fout << rt << std::setw(25) << pp_loc->splint(rt);
243 for (int l = 0; l < nl; l++)
244 fout << std::setw(25) << pp_nonloc->nlpp_m[l]->splint(rt);
245 fout << std::endl;
246 rt += d;
247 }
248 }
249 else
250 {
251 fout << "# Units = bohr hartree " << std::endl;
252 fout << "# r -r*V/zeff " << std::endl;
253 while (rt < 5)
254 {
255 fout << rt << std::setw(25) << pp_loc->splint(rt) << std::endl;
256 ;
257 rt += d;
258 }
259 }
260 }
261
SetQuadratureRule(int rule)262 void ECPComponentBuilder::SetQuadratureRule(int rule)
263 {
264 app_log() << " Quadrature Nrule: " << rule << std::endl;
265 Quadrature3D<RealType> myRule(rule);
266 pp_nonloc->sgridxyz_m = myRule.xyz_m;
267 pp_nonloc->sgridweight_m = myRule.weight_m;
268 // Allocate storage for wave function ratios
269 pp_nonloc->resize_warrays(myRule.nk, NumNonLocal, Lmax);
270 if (pp_so)
271 { //added here bc must have nonlocal terms to have SO contributions
272 pp_so->sgridxyz_m = myRule.xyz_m;
273 pp_so->sgridweight_m = myRule.weight_m;
274 pp_so->resize_warrays(myRule.nk, NumSO, Srule);
275 }
276 }
277
278 } // namespace qmcplusplus
279