1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2009-2017 The Regents of the University of California
4 //
5 // This file is part of Qbox
6 //
7 // Qbox is distributed under the terms of the GNU General Public License
8 // as published by the Free Software Foundation, either version 2 of
9 // the License, or (at your option) any later version.
10 // See the file COPYING in the root directory of this distribution
11 // or <http://www.gnu.org/licenses/>.
12 //
13 ////////////////////////////////////////////////////////////////////////////////
14 //
15 // upf2qso.cpp: transform a UPF pseudopotential to QSO format
16 // the QSO format is defined at http://www.quantum-simulation.org
17 // This program accepts both the original UPF format and the "2.0.1" format
18 //
19 ////////////////////////////////////////////////////////////////////////////////
20 //
21 // use: upf2qso rcut(a.u.) < pot.UPF > pot.xml
22 // The potentials in pot.xml are given on a radial linear grid up to rcut,
23 // with grid spacing of 0.01 (a.u.)
24 //
25 #include <iostream>
26 #include <iomanip>
27 #include <fstream>
28 #include <sstream>
29 #include <string>
30 #include <algorithm>
31 #include <vector>
32 #include <cmath>
33 #include <cassert>
34 #include <cstdlib>
35 #include <stdexcept>
36 #include "spline.h"
37 #include "isodate.h"
38 #include "PeriodicTable.h"
39 using namespace std;
40 
41 ////////////////////////////////////////////////////////////////////////////////
find_start_element(string name)42 string find_start_element(string name)
43 {
44   // return the contents of the tag at start of element "name"
45   string buf, token;
46   string search_str = "<" + name;
47   do
48   {
49     cin >> token;
50   }
51   while ( !cin.eof() && token.find(search_str) == string::npos );
52   if ( cin.eof() )
53   {
54     cerr << " EOF reached before start element " << name << endl;
55     throw invalid_argument(name);
56   }
57 
58   buf = token;
59   if ( buf[buf.length()-1] == '>' )
60     return buf;
61 
62   // read until ">" is found
63   bool found = false;
64   char ch;
65   do
66   {
67     cin.get(ch);
68     found = ch == '>';
69     buf += ch;
70   }
71   while ( !cin.eof() && !found );
72   if ( cin.eof() )
73   {
74     cerr << " EOF reached before > " << name << endl;
75     throw invalid_argument(name);
76   }
77   return buf;
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
find_end_element(string name)81 void find_end_element(string name)
82 {
83   string buf, token;
84   string search_str = "</" + name + ">";
85   do
86   {
87     cin >> token;
88     if ( token.find(search_str) != string::npos ) return;
89   }
90   while ( !cin.eof() );
91   cerr << " EOF reached before end element " << name << endl;
92   throw invalid_argument(name);
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
seek_str(string tag)96 void seek_str(string tag)
97 {
98   // Read tokens from stdin until tag is found.
99   // Throw an exception if tag not found before eof()
100   bool done = false;
101   string token;
102   int count = 0;
103 
104   do
105   {
106     cin >> token;
107     if ( token.find(tag) != string::npos ) return;
108   }
109   while ( !cin.eof() );
110 
111   cerr << " EOF reached before " << tag << endl;
112   throw invalid_argument(tag);
113 }
114 
115 ////////////////////////////////////////////////////////////////////////////////
get_attr(string buf,string attr)116 string get_attr(string buf, string attr)
117 {
118   //cerr << " get_attr: searching for: " << attr << endl;
119   //cerr << " in buffer: " << endl;
120   //cerr << buf << endl;
121   bool done = false;
122   string s, search_string = attr + "=";
123 
124   // find attribute name in buf
125   string::size_type p = buf.find(search_string);
126   if ( p != string::npos )
127   {
128     // process attribute
129     string::size_type b = buf.find_first_of("\"",p);
130     string::size_type e = buf.find_first_of("\"",b+1);
131     if ( b == string::npos || e == string::npos )
132     {
133       cerr << " get_attr: attribute not found: " << attr << endl;
134       throw invalid_argument(attr);
135     }
136     s = buf.substr(b+1,e-b-1);
137     // remove white space
138     s.erase(remove_if(s.begin(),s.end(),::isspace),s.end());
139     return s;
140   }
141   else
142   {
143     cerr << " get_attr: attribute not found: " << attr << endl;
144     throw invalid_argument(attr);
145   }
146   return s;
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
skipln(void)150 void skipln(void)
151 {
152   char ch;
153   bool found = false;
154   while ( !cin.eof() && !found )
155   {
156     cin.get(ch);
157     found = ch == '\n';
158   }
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 const string release="1.10";
163 
main(int argc,char ** argv)164 int main(int argc, char** argv)
165 {
166   cerr << " upf2qso " << release << endl;
167   if ( argc != 2 )
168   {
169     cerr << " usage: upf2qso rcut < file.upf > file.xml" << endl;
170     return 1;
171   }
172   assert(argc==2);
173   const double rcut = atof(argv[1]);
174 
175   PeriodicTable pt;
176   string buf,s;
177   istringstream is;
178 
179   // determine UPF version
180   int upf_version = 0;
181 
182   // The first line of the UPF potential file contains either of the following:
183   // <PP_INFO>  (for UPF version 1)
184   // <UPF version="2.0.1"> (for UPF version 2)
185   string::size_type p;
186   getline(cin,buf);
187   p = buf.find("<PP_INFO>");
188   if ( p != string::npos )
189     upf_version = 1;
190   else
191   {
192     p = buf.find("<UPF version=\"2.0.1\">");
193     if ( p != string::npos )
194       upf_version = 2;
195   }
196   if ( upf_version == 0 )
197   {
198     cerr << " Format of UPF file not recognized " << endl;
199     cerr << " First line of file: " << buf << endl;
200     return 1;
201   }
202 
203   cerr << " UPF version: " << upf_version << endl;
204 
205   if ( upf_version == 1 )
206   {
207     // process UPF version 1 potential
208     string upf_pp_info;
209     bool done = false;
210     while (!done)
211     {
212       getline(cin,buf);
213       is.clear();
214       is.str(buf);
215       is >> s;
216       done = ( s == "</PP_INFO>" );
217       if ( !done )
218       {
219         upf_pp_info += buf + '\n';
220       }
221     }
222 
223     // remove all '<' and '>' characters from the PP_INFO field
224     // for XML compatibility
225     p = upf_pp_info.find_first_of("<>");
226     while ( p != string::npos )
227     {
228       upf_pp_info[p] = ' ';
229       p = upf_pp_info.find_first_of("<>");
230     }
231 
232     seek_str("<PP_HEADER>");
233     skipln();
234 
235     // version number (ignore)
236     getline(cin,buf);
237 
238     // element symbol
239     string upf_symbol;
240     getline(cin,buf);
241     is.clear();
242     is.str(buf);
243     is >> upf_symbol;
244 
245     // get atomic number and mass
246     const int atomic_number = pt.z(upf_symbol);
247     const double mass = pt.mass(upf_symbol);
248 
249     // NC flag
250     string upf_ncflag;
251     getline(cin,buf);
252     is.clear();
253     is.str(buf);
254     is >> upf_ncflag;
255     if ( upf_ncflag != "NC" )
256     {
257       cerr << " not a Norm-conserving potential" << endl;
258       cerr << " NC flag: " << upf_ncflag << endl;
259       return 1;
260     }
261 
262     // NLCC flag
263     string upf_nlcc_flag;
264     getline(cin,buf);
265     is.clear();
266     is.str(buf);
267     is >> upf_nlcc_flag;
268     if ( upf_nlcc_flag == "T" )
269     {
270       cerr << " Potential includes a non-linear core correction" << endl;
271     }
272 
273     // XC functional (add in description)
274     string upf_xcf[4];
275     getline(cin,buf);
276     is.clear();
277     is.str(buf);
278     is >> upf_xcf[0] >> upf_xcf[1] >> upf_xcf[2] >> upf_xcf[3];
279 
280     // add XC functional information to description
281     upf_pp_info += upf_xcf[0] + ' ' + upf_xcf[1] + ' ' +
282                    upf_xcf[2] + ' ' + upf_xcf[3] + '\n';
283 
284     // Z valence
285     double upf_zval;
286     getline(cin,buf);
287     is.clear();
288     is.str(buf);
289     is >> upf_zval;
290 
291     // Total energy (ignore)
292     getline(cin,buf);
293 
294     // suggested cutoff (ignore)
295     getline(cin,buf);
296 
297     // max angular momentum
298     int upf_lmax;
299     getline(cin,buf);
300     is.clear();
301     is.str(buf);
302     is >> upf_lmax;
303 
304     // number of points in mesh
305     int upf_mesh_size;
306     getline(cin,buf);
307     is.clear();
308     is.str(buf);
309     is >> upf_mesh_size;
310 
311     // number of wavefunctions, number of projectors
312     int upf_nwf, upf_nproj;
313     getline(cin,buf);
314     is.clear();
315     is.str(buf);
316     is >> upf_nwf >> upf_nproj;
317 
318     // Wavefunctions
319     vector<string> upf_shell(upf_nwf);
320     vector<int> upf_l(upf_nwf);
321     vector<double> upf_occ(upf_nwf);
322     // skip header
323     getline(cin,buf);
324     for ( int ip = 0; ip < upf_nwf; ip++ )
325     {
326       getline(cin,buf);
327       is.clear();
328       is.str(buf);
329       is >> upf_shell[ip] >> upf_l[ip] >> upf_occ[ip];
330     }
331     seek_str("</PP_HEADER>");
332 
333     // read mesh
334     seek_str("<PP_MESH>");
335     seek_str("<PP_R>");
336     skipln();
337     vector<double> upf_r(upf_mesh_size);
338     for ( int i = 0; i < upf_mesh_size; i++ )
339      cin >> upf_r[i];
340     seek_str("</PP_R>");
341     seek_str("<PP_RAB>");
342     skipln();
343     vector<double> upf_rab(upf_mesh_size);
344     for ( int i = 0; i < upf_mesh_size; i++ )
345      cin >> upf_rab[i];
346     seek_str("</PP_RAB>");
347     seek_str("</PP_MESH>");
348 
349     vector<double> upf_nlcc;
350     if ( upf_nlcc_flag == "T" )
351     {
352       upf_nlcc.resize(upf_mesh_size);
353       seek_str("<PP_NLCC>");
354       skipln();
355       for ( int i = 0; i < upf_mesh_size; i++ )
356         cin >> upf_nlcc[i];
357       seek_str("</PP_NLCC>");
358     }
359 
360     seek_str("<PP_LOCAL>");
361     skipln();
362     vector<double> upf_vloc(upf_mesh_size);
363     for ( int i = 0; i < upf_mesh_size; i++ )
364       cin >> upf_vloc[i];
365     seek_str("</PP_LOCAL>");
366 
367     seek_str("<PP_NONLOCAL>");
368     skipln();
369     vector<vector<double> > upf_vnl;
370     upf_vnl.resize(upf_nproj);
371     vector<int> upf_proj_l(upf_nproj);
372     for ( int j = 0; j < upf_nproj; j++ )
373     {
374       seek_str("<PP_BETA>");
375       skipln();
376       int ip, l, np;
377       cin >> ip >> l;
378       skipln();
379       assert(ip-1 < upf_nproj);
380       assert(l <= upf_lmax);
381       upf_proj_l[ip-1] = l;
382       cin >> np;
383       upf_vnl[j].resize(upf_mesh_size);
384       for ( int i = 0; i < np; i++ )
385         cin >> upf_vnl[j][i];
386       seek_str("</PP_BETA>");
387       skipln();
388     }
389     seek_str("<PP_DIJ>");
390     skipln();
391     int upf_ndij;
392     cin >> upf_ndij;
393     skipln();
394     if ( upf_ndij != upf_nproj )
395     {
396       cerr << " Number of non-zero Dij differs from number of projectors"
397            << endl;
398       return 1;
399     }
400 
401     vector<double> upf_d(upf_ndij);
402     for ( int i = 0; i < upf_ndij; i++ )
403     {
404       int m,n;
405       cin >> m >> n >> upf_d[i];
406       if ( m != n )
407       {
408         cerr << " Non-local Dij has off-diagonal elements" << endl;
409         cerr << " m=" << m << " n=" << n << endl;
410         return 1;
411       }
412     }
413     seek_str("</PP_DIJ>");
414 
415     seek_str("</PP_NONLOCAL>");
416 
417     // make table iproj[l] mapping l to iproj
418     // vnl(l) is in vnl[iproj[l]] if iproj[l] > -1
419     // vlocal if iproj[llocal] = -1
420     vector<int> iproj(upf_lmax+2);
421     for ( int l = 0; l <= upf_lmax+1; l++ )
422       iproj[l] = -1;
423     for ( int j = 0; j < upf_nproj; j++ )
424       iproj[upf_proj_l[j]] = j;
425 
426     // determine angular momentum of local potential in UPF file
427     int upf_llocal;
428     // reverse loop to get correct upf_llocal when upf_nproj < upf_lmax
429     for ( int l = upf_lmax+1; l >= 0; l-- )
430       if ( iproj[l] == -1 )
431         upf_llocal = l;
432     // increase lmax if there are more projectors than wavefunctions
433     int qso_lmax = upf_lmax;
434     if (upf_lmax < upf_llocal)
435     {
436       qso_lmax = upf_lmax+1;
437     }
438 
439     seek_str("<PP_PSWFC>");
440     skipln();
441     vector<vector<double> > upf_wf;
442     vector<int> upf_wf_l(upf_nwf);
443     vector<double> upf_wf_occ(upf_nwf);
444     upf_wf.resize(upf_nwf);
445     for ( int j = 0; j < upf_nwf; j++ )
446     {
447       upf_wf[j].resize(upf_mesh_size);
448       string label;
449       cin >> label >> upf_wf_l[j] >> upf_wf_occ[j];
450       skipln();
451       for ( int i = 0; i < upf_mesh_size; i++ )
452         cin >> upf_wf[j][i];
453     }
454     seek_str("</PP_PSWFC>");
455 
456     // output original data in file upf.dat
457     ofstream upf("upf.dat");
458     upf << "# vloc" << endl;
459     for ( int i = 0; i < upf_vloc.size(); i++ )
460       upf << upf_r[i] << " " << upf_vloc[i] << endl;
461     upf << endl << endl;
462     for ( int j = 0; j < upf_nproj; j++ )
463     {
464       upf << "# proj j=" << j << endl;
465       for ( int i = 0; i < upf_vnl[j].size(); i++ )
466         upf << upf_r[i] << " " << upf_vnl[j][i] << endl;
467       upf << endl << endl;
468     }
469     for ( int j = 0; j < upf_nwf; j++ )
470     {
471       upf << "# wf j=" << j << endl;
472       for ( int i = 0; i < upf_wf[j].size(); i++ )
473         upf << upf_r[i] << " " << upf_wf[j][i] << endl;
474       upf << endl << endl;
475     }
476     upf.close();
477 
478 
479     // print summary
480     cerr << "PP_INFO:" << endl << upf_pp_info << endl;
481     cerr << "Element: " << upf_symbol << endl;
482     cerr << "NC: " << upf_ncflag << endl;
483     cerr << "NLCC: " << upf_nlcc_flag << endl;
484     cerr << "XC: " << upf_xcf[0] << " " << upf_xcf[1] << " "
485          << upf_xcf[2] << " " << upf_xcf[3] << endl;
486     cerr << "Zv: " << upf_zval << endl;
487     cerr << "lmax: " << qso_lmax << endl;
488     cerr << "llocal: " << upf_llocal << endl;
489     cerr << "nwf: " << upf_nwf << endl;
490     cerr << "mesh_size: " << upf_mesh_size << endl;
491 
492     // compute delta_vnl[l][i] on the upf log mesh
493 
494     // divide the projector function by the wavefunction, except if
495     // the wavefunction amplitude is smaller than tol, outside of rcut_divide.
496     const double tol = 1.e-5;
497     const double rcut_divide = 1.0;
498     vector<vector<double> > delta_vnl;
499     delta_vnl.resize(upf_nproj);
500     for ( int j = 0; j < upf_nproj; j++ )
501     {
502       delta_vnl[j].resize(upf_wf[j].size());
503       for ( int i = 0; i < delta_vnl[j].size(); i++ )
504       {
505         double num = upf_vnl[j][i];
506         double den = upf_wf[upf_proj_l[j]][i];
507 
508         delta_vnl[j][i] = 0.0;
509         if ( upf_r[i] < rcut_divide )
510         {
511           // near the origin
512           if ( i == 0 && fabs(den) < tol )
513           {
514             // i = 0 for linear mesh, r = 0.0: use nearest value
515             delta_vnl[j][i] = upf_vnl[j][1] / upf_wf[upf_proj_l[j]][1];
516           }
517           else
518           {
519             // other points near the origin
520             delta_vnl[j][i] = num / den;
521           }
522         }
523         else
524         {
525           // wavefunction gets small at large r.
526           // Assume that delta_vnl is zero when that happens
527           if ( fabs(den) > tol )
528             delta_vnl[j][i] = num / den;
529         }
530       }
531     }
532 
533     vector<vector<double> > vps;
534     vps.resize(upf_nproj+1);
535     for ( int j = 0; j < upf_nproj; j++ )
536     {
537       vps[j].resize(upf_mesh_size);
538       for ( int i = 0; i < delta_vnl[j].size(); i++ )
539         vps[j][i] = upf_vloc[i] + delta_vnl[j][i];
540     }
541 
542     // interpolate functions on linear mesh
543     const double mesh_spacing = 0.01;
544     int nplin = (int) (rcut / mesh_spacing);
545     vector<double> f(upf_mesh_size), fspl(upf_mesh_size);
546 
547     vector<double> nlcc_lin(nplin);
548     // interpolate NLCC
549     if ( upf_nlcc_flag == "T" )
550     {
551       assert(upf_mesh_size==upf_nlcc.size());
552       for ( int i = 0; i < upf_nlcc.size(); i++ )
553         f[i] = upf_nlcc[i];
554       int n = upf_nlcc.size();
555       int bcnat_left = 0;
556       double yp_left = 0.0;
557       int bcnat_right = 1;
558       double yp_right = 0.0;
559       spline(n,&upf_r[0],&f[0],yp_left,yp_right,
560              bcnat_left,bcnat_right,&fspl[0]);
561 
562       for ( int i = 0; i < nplin; i++ )
563       {
564         double r = i * mesh_spacing;
565         if ( r >= upf_r[0] )
566           splint(n,&upf_r[0],&f[0],&fspl[0],r,&nlcc_lin[i]);
567         else
568           // use value closest to the origin for r=0
569           nlcc_lin[i] = upf_nlcc[0];
570         if ( fabs(nlcc_lin[i]) < 1.e-12 )
571           nlcc_lin[i] = 0.0;
572       }
573     }
574 
575     // interpolate vloc
576     // factor 0.5: convert from Ry in UPF to Hartree in QSO
577     for ( int i = 0; i < upf_vloc.size(); i++ )
578       f[i] = 0.5 * upf_vloc[i];
579 
580     int n = upf_vloc.size();
581     int bcnat_left = 0;
582     double yp_left = 0.0;
583     int bcnat_right = 1;
584     double yp_right = 0.0;
585     spline(n,&upf_r[0],&f[0],yp_left,yp_right,
586            bcnat_left,bcnat_right,&fspl[0]);
587 
588     vector<double> vloc_lin(nplin);
589     for ( int i = 0; i < nplin; i++ )
590     {
591       double r = i * mesh_spacing;
592       if ( r >= upf_r[0] )
593         splint(n,&upf_r[0],&f[0],&fspl[0],r,&vloc_lin[i]);
594       else
595         // use value closest to the origin for r=0
596         vloc_lin[i] = 0.5 * upf_vloc[0];
597     }
598 
599     // interpolate vps[j], j=0, nproj-1
600     vector<vector<double> > vps_lin;
601     vps_lin.resize(vps.size());
602     for ( int j = 0; j < vps.size(); j++ )
603     {
604       vps_lin[j].resize(nplin);
605     }
606 
607     for ( int j = 0; j < upf_nproj; j++ )
608     {
609       // factor 0.5: convert from Ry in UPF to Hartree in QSO
610       for ( int i = 0; i < upf_vloc.size(); i++ )
611         f[i] = 0.5 * vps[j][i];
612 
613       int n = upf_vloc.size();
614       int bcnat_left = 0;
615       double yp_left = 0.0;
616       int bcnat_right = 1;
617       double yp_right = 0.0;
618       spline(n,&upf_r[0],&f[0],yp_left,yp_right,
619              bcnat_left,bcnat_right,&fspl[0]);
620 
621       for ( int i = 0; i < nplin; i++ )
622       {
623         double r = i * mesh_spacing;
624         if ( r >= upf_r[0] )
625           splint(n,&upf_r[0],&f[0],&fspl[0],r,&vps_lin[j][i]);
626         else
627           vps_lin[j][i] = 0.5 * vps[j][0];
628       }
629     }
630 
631     // write potentials in gnuplot format on file vlin.dat
632     ofstream vlin("vlin.dat");
633     for ( int l = 0; l <= qso_lmax; l++ )
634     {
635       vlin << "# v, l=" << l << endl;
636       if ( iproj[l] == -1 )
637       {
638         // l == llocal
639         for ( int i = 0; i < nplin; i++ )
640           vlin << i*mesh_spacing << " " << vloc_lin[i] << endl;
641         vlin << endl << endl;
642       }
643       else
644       {
645         for ( int i = 0; i < nplin; i++ )
646           vlin << i*mesh_spacing << " " << vps_lin[iproj[l]][i] << endl;
647         vlin << endl << endl;
648       }
649     }
650 
651     // interpolate wavefunctions on the linear mesh
652 
653     vector<vector<double> > wf_lin;
654     wf_lin.resize(upf_nwf);
655     for ( int j = 0; j < upf_nwf; j++ )
656     {
657       wf_lin[j].resize(nplin);
658       assert(upf_wf[j].size()<=f.size());
659       for ( int i = 0; i < upf_wf[j].size(); i++ )
660       {
661         if ( upf_r[i] > 0.0 )
662           f[i] = upf_wf[j][i] / upf_r[i];
663         else
664         {
665           // value at origin, depending on angular momentum
666           if ( upf_wf_l[j] == 0 )
667           {
668             // l=0: take value closest to r=0
669             f[i] = upf_wf[j][1]/upf_r[1];
670           }
671           else
672           {
673             // l>0:
674             f[i] = 0.0;
675           }
676         }
677       }
678 
679       int n = upf_wf[j].size();
680       // choose boundary condition at origin depending on angular momentum
681       int bcnat_left = 0;
682       double yp_left = 0.0;
683       if ( upf_wf_l[j] == 1 )
684       {
685         bcnat_left = 1; // use natural bc
686         double yp_left = 0.0; // not used
687       }
688       int bcnat_right = 1;
689       double yp_right = 0.0;
690       spline(n,&upf_r[0],&f[0],yp_left,yp_right,
691              bcnat_left,bcnat_right,&fspl[0]);
692 
693       for ( int i = 0; i < nplin; i++ )
694       {
695         double r = i * mesh_spacing;
696         if ( r >= upf_r[0] )
697           splint(n,&upf_r[0],&f[0],&fspl[0],r,&wf_lin[j][i]);
698         else
699         {
700           // r < upf_r[0]
701           assert(upf_r[0]>0.0);
702           // compute value near origin, depending on angular momentum
703           if ( upf_wf_l[j] == 0 )
704           {
705             // l=0: take value closest to r=0
706             wf_lin[j][i] = upf_wf[j][0]/upf_r[0];
707           }
708           else
709           {
710             // l>0:
711             wf_lin[j][i] = upf_wf[j][0] * r / ( upf_r[0] * upf_r[0] );
712           }
713         }
714       }
715 
716       vlin << "# phi, l=" << upf_l[j] << endl;
717       for ( int i = 0; i < nplin; i++ )
718         vlin << i*mesh_spacing << " " << wf_lin[j][i] << endl;
719       vlin << endl << endl;
720     }
721 
722     cerr << " interpolation done" << endl;
723 
724 #if 1
725     // output potential on log mesh
726     ofstream vout("v.dat");
727     for ( int l = 0; l <= qso_lmax; l++ )
728     {
729       vout << "# v, l=" << l << endl;
730       if ( iproj[l] == -1 )
731       {
732         // l == llocal
733         for ( int i = 0; i < upf_vloc.size(); i++ )
734           vout << upf_r[i] << " " << 0.5*upf_vloc[i] << endl;
735         vout << endl << endl;
736       }
737       else
738       {
739         for ( int i = 0; i < vps[iproj[l]].size(); i++ )
740           vout << upf_r[i] << " " << 0.5*vps[iproj[l]][i] << endl;
741         vout << endl << endl;
742       }
743     }
744     vout << endl << endl;
745     vout.close();
746 #endif
747 
748     // Generate QSO file
749 
750     // output potential in QSO format
751     cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
752     cout << "<fpmd:species xmlns:fpmd=\"http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0\"" << endl;
753     cout << "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << endl;
754     cout << "  xsi:schemaLocation=\"http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0"  << endl;
755     cout << "  species.xsd\">" << endl;
756     cout << "<description>" << endl;
757     cout << "Translated from UPF format by upf2qso " << release
758          << " on " << isodate() << endl;
759     cout << upf_pp_info;
760     cout << "</description>" << endl;
761     cout << "<symbol>" << upf_symbol << "</symbol>" << endl;
762     cout << "<atomic_number>" << atomic_number << "</atomic_number>" << endl;
763     cout << "<mass>" << mass << "</mass>" << endl;
764     cout << "<norm_conserving_pseudopotential>" << endl;
765     cout << "<valence_charge>" << upf_zval << "</valence_charge>" << endl;
766     cout << "<lmax>" << qso_lmax << "</lmax>" << endl;
767     cout << "<llocal>" << upf_llocal << "</llocal>" << endl;
768     cout << "<nquad>0</nquad>" << endl;
769     cout << "<rquad>0.0</rquad>" << endl;
770     cout << "<mesh_spacing>" << mesh_spacing << "</mesh_spacing>" << endl;
771 
772     cout.setf(ios::scientific,ios::floatfield);
773     if ( upf_nlcc_flag == "T" )
774     {
775       cout << "<core_density size=\"" << nplin << "\">" << endl;
776       for ( int i = 0; i < nplin; i++ )
777         cout << setprecision(10) << nlcc_lin[i] << endl;
778       cout << "</core_density>" << endl;
779     }
780 
781     for ( int l = 0; l <= qso_lmax; l++ )
782     {
783       cout << "<projector l=\"" << l << "\" size=\"" << nplin << "\">"
784            << endl;
785       cout << "<radial_potential>" << endl;
786       if ( iproj[l] == -1 )
787       {
788         // l == llocal
789         for ( int i = 0; i < nplin; i++ )
790           cout << setprecision(10) << vloc_lin[i] << endl;
791       }
792       else
793       {
794         for ( int i = 0; i < nplin; i++ )
795           cout << setprecision(10) << vps_lin[iproj[l]][i] << endl;
796       }
797       cout << "</radial_potential>" << endl;
798       // find index j corresponding to angular momentum l
799       int j = 0;
800       while ( upf_wf_l[j] != l && j < upf_nwf ) j++;
801       // check if found
802       const bool found = ( j != upf_nwf );
803       // print wf only if found
804       if ( found )
805       {
806         cout << "<radial_function>" << endl;
807         for ( int i = 0; i < nplin; i++ )
808           cout << setprecision(10) << wf_lin[j][i] << endl;
809         cout << "</radial_function>" << endl;
810       }
811       cout << "</projector>" << endl;
812     }
813     cout << "</norm_conserving_pseudopotential>" << endl;
814     cout << "</fpmd:species>" << endl;
815 
816   }
817   else if ( upf_version == 2 )
818   {
819     // process UPF version 2 potential
820     seek_str("<PP_INFO>");
821     string upf_pp_info;
822     bool done = false;
823     while (!done)
824     {
825       getline(cin,buf);
826       is.clear();
827       is.str(buf);
828       is >> s;
829       done = ( s == "</PP_INFO>" );
830       if ( !done )
831       {
832         upf_pp_info += buf + '\n';
833       }
834     }
835 
836     // remove all '<' and '>' characters from the PP_INFO field
837     // for XML compatibility
838     p = upf_pp_info.find_first_of("<>");
839     while ( p != string::npos )
840     {
841       upf_pp_info[p] = ' ';
842       p = upf_pp_info.find_first_of("<>");
843     }
844 
845     string tag = find_start_element("PP_HEADER");
846 
847     // get attribute "element"
848     string upf_symbol = get_attr(tag,"element");
849     cerr << " upf_symbol: " << upf_symbol << endl;
850 
851     // get atomic number and mass
852     const int atomic_number = pt.z(upf_symbol);
853     const double mass = pt.mass(upf_symbol);
854 
855     // check if potential is norm-conserving or semi-local
856     string pseudo_type = get_attr(tag,"pseudo_type");
857     cerr << " pseudo_type = " << pseudo_type << endl;
858     if ( pseudo_type!="NC" && pseudo_type!="SL" )
859     {
860       cerr << " pseudo_type must be NC or SL" << endl;
861       return 1;
862     }
863 
864     // NLCC flag
865     string upf_nlcc_flag = get_attr(tag,"core_correction");
866     if ( upf_nlcc_flag == "T" )
867     {
868       cerr << " Potential includes a non-linear core correction" << endl;
869     }
870     cerr << " upf_nlcc_flag = " << upf_nlcc_flag << endl;
871 
872     // XC functional (add in description)
873     string upf_functional = get_attr(tag,"functional");
874     // add XC functional information to description
875     upf_pp_info += "functional = " + upf_functional + '\n';
876     cerr << " upf_functional = " << upf_functional << endl;
877 
878     // valence charge
879     double upf_zval = 0.0;
880     string buf = get_attr(tag,"z_valence");
881     is.clear();
882     is.str(buf);
883     is >> upf_zval;
884     cerr << " upf_zval = " << upf_zval << endl;
885 
886     // max angular momentum
887     int upf_lmax;
888     buf = get_attr(tag,"l_max");
889     is.clear();
890     is.str(buf);
891     is >> upf_lmax;
892     cerr << " upf_lmax = " << upf_lmax << endl;
893 
894     // local angular momentum
895     int upf_llocal;
896     buf = get_attr(tag,"l_local");
897     is.clear();
898     is.str(buf);
899     is >> upf_llocal;
900     cerr << " upf_llocal = " << upf_llocal << endl;
901 
902     // number of points in mesh
903     int upf_mesh_size;
904     buf = get_attr(tag,"mesh_size");
905     is.clear();
906     is.str(buf);
907     is >> upf_mesh_size;
908     cerr << " upf_mesh_size = " << upf_mesh_size << endl;
909 
910     // number of wavefunctions
911     int upf_nwf;
912     buf = get_attr(tag,"number_of_wfc");
913     is.clear();
914     is.str(buf);
915     is >> upf_nwf;
916     cerr << " upf_nwf = " << upf_nwf << endl;
917 
918     // number of projectors
919     int upf_nproj;
920     buf = get_attr(tag,"number_of_proj");
921     is.clear();
922     is.str(buf);
923     is >> upf_nproj;
924     cerr << " upf_nproj = " << upf_nproj << endl;
925 
926     vector<int> upf_l(upf_nwf);
927 
928     // read mesh
929     find_start_element("PP_MESH");
930     find_start_element("PP_R");
931     vector<double> upf_r(upf_mesh_size);
932     for ( int i = 0; i < upf_mesh_size; i++ )
933       cin >> upf_r[i];
934     find_end_element("PP_R");
935     find_start_element("PP_RAB");
936     vector<double> upf_rab(upf_mesh_size);
937     for ( int i = 0; i < upf_mesh_size; i++ )
938       cin >> upf_rab[i];
939     find_end_element("PP_RAB");
940     find_end_element("PP_MESH");
941 
942     find_start_element("PP_LOCAL");
943     vector<double> upf_vloc(upf_mesh_size);
944     for ( int i = 0; i < upf_mesh_size; i++ )
945       cin >> upf_vloc[i];
946     find_end_element("PP_LOCAL");
947 
948     find_start_element("PP_NONLOCAL");
949     vector<vector<double> > upf_vnl;
950     upf_vnl.resize(upf_nproj);
951     vector<int> upf_proj_l(upf_nproj);
952 
953     ostringstream os;
954     for ( int j = 0; j < upf_nproj; j++ )
955     {
956       int index, angular_momentum;
957       os.str("");
958       os << j+1;
959       string element_name = "PP_BETA." + os.str();
960       tag = find_start_element(element_name);
961       cerr << tag << endl;
962 
963       buf = get_attr(tag,"index");
964       is.clear();
965       is.str(buf);
966       is >> index;
967       cerr << " index = " << index << endl;
968 
969       buf = get_attr(tag,"angular_momentum");
970       is.clear();
971       is.str(buf);
972       is >> angular_momentum;
973       cerr << " angular_momentum = " << angular_momentum << endl;
974 
975       assert(angular_momentum <= upf_lmax);
976       upf_proj_l[index-1] = angular_momentum;
977 
978       upf_vnl[j].resize(upf_mesh_size);
979       for ( int i = 0; i < upf_mesh_size; i++ )
980         cin >> upf_vnl[j][i];
981 
982       find_end_element(element_name);
983     }
984 
985     // compute number of projectors for each l
986     // nproj_l[l] is the number of projectors having angular momentum l
987     vector<int> nproj_l(upf_lmax+1);
988     for ( int l = 0; l <= upf_lmax; l++ )
989     {
990       nproj_l[l] = 0;
991       for ( int ip = 0; ip < upf_nproj; ip++ )
992         if ( upf_proj_l[ip] == l ) nproj_l[l]++;
993     }
994 
995     tag = find_start_element("PP_DIJ");
996     int size;
997     buf = get_attr(tag,"size");
998     is.clear();
999     is.str(buf);
1000     is >> size;
1001     cerr << "PP_DIJ size = " << size << endl;
1002 
1003     if ( size != upf_nproj*upf_nproj )
1004     {
1005       cerr << " Number of non-zero Dij differs from number of projectors"
1006            << endl;
1007       return 1;
1008     }
1009     int upf_ndij = size;
1010 
1011     vector<double> upf_d(upf_ndij);
1012     for ( int i = 0; i < upf_ndij; i++ )
1013     {
1014       cin >> upf_d[i];
1015     }
1016     int imax = sqrt(size+1.e-5);
1017     assert(imax*imax==size);
1018 
1019     // Check if Dij has non-diagonal elements
1020     // non-diagonal elements are not supported
1021     for ( int m = 0; m < imax; m++ )
1022       for ( int n = 0; n < imax; n++ )
1023         if ( (m != n) && (upf_d[n*imax+m] != 0.0) )
1024         {
1025           cerr << " Non-local Dij has off-diagonal elements" << endl;
1026           cerr << " m=" << m << " n=" << n << endl;
1027           return 1;
1028         }
1029 
1030     find_end_element("PP_DIJ");
1031 
1032     find_end_element("PP_NONLOCAL");
1033 
1034     // make table iproj[l] mapping l to iproj
1035     // vnl(l) is in vnl[iproj[l]] if iproj[l] > -1
1036     // vlocal if iproj[llocal] = -1
1037     vector<int> iproj(upf_lmax+2);
1038     for ( int l = 0; l <= upf_lmax+1; l++ )
1039       iproj[l] = -1;
1040     for ( int j = 0; j < upf_nproj; j++ )
1041       iproj[upf_proj_l[j]] = j;
1042 
1043     // determine angular momentum of local potential in UPF file
1044     // upf_llocal is the angular momentum of the local potential
1045     // increase lmax if there are more projectors than wavefunctions
1046     int qso_lmax = upf_lmax;
1047     if (upf_lmax < upf_llocal)
1048     {
1049       qso_lmax = upf_lmax+1;
1050     }
1051 
1052     if ( pseudo_type == "SL" )
1053     {
1054       find_start_element("PP_PSWFC");
1055       vector<vector<double> > upf_wf;
1056       vector<int> upf_wf_l(upf_nwf);
1057       upf_wf.resize(upf_nwf);
1058       for ( int j = 0; j < upf_nwf; j++ )
1059       {
1060         int index, l;
1061         os.str("");
1062         os << j+1;
1063         string element_name = "PP_CHI." + os.str();
1064         tag = find_start_element(element_name);
1065         cerr << tag << endl;
1066 
1067         buf = get_attr(tag,"index");
1068         is.clear();
1069         is.str(buf);
1070         is >> index;
1071         cerr << " index = " << index << endl;
1072 
1073         buf = get_attr(tag,"l");
1074         is.clear();
1075         is.str(buf);
1076         is >> l;
1077         cerr << " l = " << l << endl;
1078 
1079         assert(l <= upf_lmax);
1080         upf_proj_l[index-1] = l;
1081         upf_wf[j].resize(upf_mesh_size);
1082         for ( int i = 0; i < upf_mesh_size; i++ )
1083           cin >> upf_wf[j][i];
1084       }
1085       find_end_element("PP_PSWFC");
1086 
1087       // NLCC
1088       vector<double> upf_nlcc;
1089       if ( upf_nlcc_flag == "T" )
1090       {
1091         find_start_element("PP_NLCC");
1092         upf_nlcc.resize(upf_mesh_size);
1093         for ( int i = 0; i < upf_mesh_size; i++ )
1094           cin >> upf_nlcc[i];
1095         find_end_element("PP_NLCC");
1096       }
1097 
1098       // output original data in file upf.dat
1099       ofstream upf("upf.dat");
1100       upf << "# vloc" << endl;
1101       for ( int i = 0; i < upf_vloc.size(); i++ )
1102         upf << upf_r[i] << " " << upf_vloc[i] << endl;
1103       upf << endl << endl;
1104       for ( int j = 0; j < upf_nproj; j++ )
1105       {
1106         upf << "# proj j=" << j << endl;
1107         for ( int i = 0; i < upf_vnl[j].size(); i++ )
1108           upf << upf_r[i] << " " << upf_vnl[j][i] << endl;
1109         upf << endl << endl;
1110       }
1111       for ( int j = 0; j < upf_nwf; j++ )
1112       {
1113         upf << "# wf j=" << j << endl;
1114         for ( int i = 0; i < upf_wf[j].size(); i++ )
1115           upf << upf_r[i] << " " << upf_wf[j][i] << endl;
1116         upf << endl << endl;
1117       }
1118       upf.close();
1119 
1120       // print summary
1121       cerr << "PP_INFO:" << endl << upf_pp_info << endl;
1122       cerr << "Element: " << upf_symbol << endl;
1123        cerr << "NLCC: " << upf_nlcc_flag << endl;
1124       //cerr << "XC: " << upf_xcf[0] << " " << upf_xcf[1] << " "
1125       //     << upf_xcf[2] << " " << upf_xcf[3] << endl;
1126       cerr << "Zv: " << upf_zval << endl;
1127       cerr << "lmax: " << qso_lmax << endl;
1128       cerr << "llocal: " << upf_llocal << endl;
1129       cerr << "nwf: " << upf_nwf << endl;
1130       cerr << "mesh_size: " << upf_mesh_size << endl;
1131 
1132       // compute delta_vnl[l][i] on the upf log mesh
1133 
1134       // divide the projector function by the wavefunction, except if
1135       // the wavefunction amplitude is smaller than tol, outside of rcut_divide.
1136       const double tol = 1.e-5;
1137       const double rcut_divide = 1.0;
1138       vector<vector<double> > delta_vnl;
1139       delta_vnl.resize(upf_nproj);
1140       for ( int j = 0; j < upf_nproj; j++ )
1141       {
1142         delta_vnl[j].resize(upf_wf[j].size());
1143         for ( int i = 0; i < delta_vnl[j].size(); i++ )
1144         {
1145           double num = upf_vnl[j][i];
1146           double den = upf_wf[upf_proj_l[j]][i];
1147 
1148           delta_vnl[j][i] = 0.0;
1149           if ( upf_r[i] < rcut_divide )
1150           {
1151             // near the origin
1152             if ( i == 0 && fabs(den) < tol )
1153             {
1154               // i = 0 for linear mesh, r = 0.0: use nearest value
1155               delta_vnl[j][i] = upf_vnl[j][1] / upf_wf[upf_proj_l[j]][1];
1156             }
1157             else
1158             {
1159               // other points near the origin
1160               delta_vnl[j][i] = num / den;
1161             }
1162           }
1163           else
1164           {
1165             // wavefunction gets small at large r.
1166             // Assume that delta_vnl is zero when that happens
1167             if ( fabs(den) > tol )
1168               delta_vnl[j][i] = num / den;
1169           }
1170         }
1171       }
1172 
1173       vector<vector<double> > vps;
1174       vps.resize(upf_nproj+1);
1175       for ( int j = 0; j < upf_nproj; j++ )
1176       {
1177         vps[j].resize(upf_mesh_size);
1178         for ( int i = 0; i < delta_vnl[j].size(); i++ )
1179           vps[j][i] = upf_vloc[i] + delta_vnl[j][i];
1180       }
1181 
1182       // interpolate functions on linear mesh
1183       const double mesh_spacing = 0.01;
1184       int nplin = (int) (rcut / mesh_spacing);
1185       vector<double> f(upf_mesh_size), fspl(upf_mesh_size);
1186 
1187       // interpolate NLCC
1188       vector<double> nlcc_lin(nplin);
1189       if ( upf_nlcc_flag == "T" )
1190       {
1191         assert(upf_mesh_size==upf_nlcc.size());
1192         for ( int i = 0; i < upf_nlcc.size(); i++ )
1193           f[i] = upf_nlcc[i];
1194         int n = upf_nlcc.size();
1195         int bcnat_left = 0;
1196         double yp_left = 0.0;
1197         int bcnat_right = 1;
1198         double yp_right = 0.0;
1199         spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1200                bcnat_left,bcnat_right,&fspl[0]);
1201 
1202         for ( int i = 0; i < nplin; i++ )
1203         {
1204           double r = i * mesh_spacing;
1205           if ( r >= upf_r[0] )
1206             splint(n,&upf_r[0],&f[0],&fspl[0],r,&nlcc_lin[i]);
1207           else
1208             // use value closest to the origin for r=0
1209             nlcc_lin[i] = upf_nlcc[0];
1210           if ( fabs(nlcc_lin[i]) < 1.e-12 )
1211             nlcc_lin[i] = 0.0;
1212         }
1213       }
1214 
1215       // interpolate vloc
1216       // factor 0.5: convert from Ry in UPF to Hartree in QSO
1217       for ( int i = 0; i < upf_vloc.size(); i++ )
1218         f[i] = 0.5 * upf_vloc[i];
1219 
1220       int n = upf_vloc.size();
1221       int bcnat_left = 0;
1222       double yp_left = 0.0;
1223       int bcnat_right = 1;
1224       double yp_right = 0.0;
1225       spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1226              bcnat_left,bcnat_right,&fspl[0]);
1227 
1228       vector<double> vloc_lin(nplin);
1229       for ( int i = 0; i < nplin; i++ )
1230       {
1231         double r = i * mesh_spacing;
1232         if ( r >= upf_r[0] )
1233           splint(n,&upf_r[0],&f[0],&fspl[0],r,&vloc_lin[i]);
1234         else
1235           // use value closest to the origin for r=0
1236           vloc_lin[i] = 0.5 * upf_vloc[0];
1237       }
1238 
1239       // interpolate vps[j], j=0, nproj-1
1240       vector<vector<double> > vps_lin;
1241       vps_lin.resize(vps.size());
1242       for ( int j = 0; j < vps.size(); j++ )
1243       {
1244         vps_lin[j].resize(nplin);
1245       }
1246 
1247       for ( int j = 0; j < upf_nproj; j++ )
1248       {
1249         // factor 0.5: convert from Ry in UPF to Hartree in QSO
1250         for ( int i = 0; i < upf_vloc.size(); i++ )
1251           f[i] = 0.5 * vps[j][i];
1252 
1253         int n = upf_vloc.size();
1254         int bcnat_left = 0;
1255         double yp_left = 0.0;
1256         int bcnat_right = 1;
1257         double yp_right = 0.0;
1258         spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1259                bcnat_left,bcnat_right,&fspl[0]);
1260 
1261         for ( int i = 0; i < nplin; i++ )
1262         {
1263           double r = i * mesh_spacing;
1264           if ( r >= upf_r[0] )
1265             splint(n,&upf_r[0],&f[0],&fspl[0],r,&vps_lin[j][i]);
1266           else
1267             vps_lin[j][i] = 0.5 * vps[j][0];
1268         }
1269       }
1270 
1271       // write potentials in gnuplot format on file vlin.dat
1272       ofstream vlin("vlin.dat");
1273       for ( int l = 0; l <= qso_lmax; l++ )
1274       {
1275         vlin << "# v, l=" << l << endl;
1276         if ( iproj[l] == -1 )
1277         {
1278           // l == llocal
1279           for ( int i = 0; i < nplin; i++ )
1280             vlin << i*mesh_spacing << " " << vloc_lin[i] << endl;
1281           vlin << endl << endl;
1282         }
1283         else
1284         {
1285           for ( int i = 0; i < nplin; i++ )
1286             vlin << i*mesh_spacing << " " << vps_lin[iproj[l]][i] << endl;
1287           vlin << endl << endl;
1288         }
1289       }
1290 
1291       // interpolate wavefunctions on the linear mesh
1292 
1293       vector<vector<double> > wf_lin;
1294       wf_lin.resize(upf_nwf);
1295       for ( int j = 0; j < upf_nwf; j++ )
1296       {
1297         wf_lin[j].resize(nplin);
1298         assert(upf_wf[j].size()<=f.size());
1299         for ( int i = 0; i < upf_wf[j].size(); i++ )
1300         {
1301           if ( upf_r[i] > 0.0 )
1302             f[i] = upf_wf[j][i] / upf_r[i];
1303           else
1304           {
1305             // value at origin, depending on angular momentum
1306             if ( upf_wf_l[j] == 0 )
1307             {
1308               // l=0: take value closest to r=0
1309               f[i] = upf_wf[j][1]/upf_r[1];
1310             }
1311             else
1312             {
1313               // l>0:
1314               f[i] = 0.0;
1315             }
1316           }
1317         }
1318 
1319         int n = upf_wf[j].size();
1320         // choose boundary condition at origin depending on angular momentum
1321         int bcnat_left = 0;
1322         double yp_left = 0.0;
1323         if ( upf_wf_l[j] == 1 )
1324         {
1325           bcnat_left = 1; // use natural bc
1326           double yp_left = 0.0; // not used
1327         }
1328         int bcnat_right = 1;
1329         double yp_right = 0.0;
1330         spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1331                bcnat_left,bcnat_right,&fspl[0]);
1332 
1333         for ( int i = 0; i < nplin; i++ )
1334         {
1335           double r = i * mesh_spacing;
1336           if ( r >= upf_r[0] )
1337             splint(n,&upf_r[0],&f[0],&fspl[0],r,&wf_lin[j][i]);
1338           else
1339           {
1340             // r < upf_r[0]
1341             assert(upf_r[0]>0.0);
1342             // compute value near origin, depending on angular momentum
1343             if ( upf_wf_l[j] == 0 )
1344             {
1345               // l=0: take value closest to r=0
1346               wf_lin[j][i] = upf_wf[j][0]/upf_r[0];
1347             }
1348             else
1349             {
1350               // l>0:
1351               wf_lin[j][i] = upf_wf[j][0] * r / ( upf_r[0] * upf_r[0] );
1352             }
1353           }
1354         }
1355 
1356         vlin << "# phi, l=" << upf_l[j] << endl;
1357         for ( int i = 0; i < nplin; i++ )
1358           vlin << i*mesh_spacing << " " << wf_lin[j][i] << endl;
1359         vlin << endl << endl;
1360       }
1361 
1362       cerr << " interpolation done" << endl;
1363 
1364   #if 1
1365       // output potential on log mesh
1366       ofstream vout("v.dat");
1367       for ( int l = 0; l <= qso_lmax; l++ )
1368       {
1369         vout << "# v, l=" << l << endl;
1370         if ( iproj[l] == -1 )
1371         {
1372           // l == llocal
1373           for ( int i = 0; i < upf_vloc.size(); i++ )
1374             vout << upf_r[i] << " " << 0.5*upf_vloc[i] << endl;
1375           vout << endl << endl;
1376         }
1377         else
1378         {
1379           for ( int i = 0; i < vps[iproj[l]].size(); i++ )
1380             vout << upf_r[i] << " " << 0.5*vps[iproj[l]][i] << endl;
1381           vout << endl << endl;
1382         }
1383       }
1384       vout << endl << endl;
1385       vout.close();
1386   #endif
1387 
1388       // Generate QSO file
1389 
1390       // output potential in QSO format
1391       cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
1392       cout << "<fpmd:species xmlns:fpmd=\"http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0\"" << endl;
1393       cout << "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << endl;
1394       cout << "  xsi:schemaLocation=\"http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0"  << endl;
1395       cout << "  species.xsd\">" << endl;
1396       cout << "<description>" << endl;
1397       cout << "Translated from UPF format by upf2qso " << release
1398            << " on " << isodate() << endl;
1399       cout << upf_pp_info;
1400       cout << "</description>" << endl;
1401       cout << "<symbol>" << upf_symbol << "</symbol>" << endl;
1402       cout << "<atomic_number>" << atomic_number << "</atomic_number>" << endl;
1403       cout << "<mass>" << mass << "</mass>" << endl;
1404       cout << "<norm_conserving_pseudopotential>" << endl;
1405       cout << "<valence_charge>" << upf_zval << "</valence_charge>" << endl;
1406       cout << "<lmax>" << qso_lmax << "</lmax>" << endl;
1407       cout << "<llocal>" << upf_llocal << "</llocal>" << endl;
1408       cout << "<nquad>0</nquad>" << endl;
1409       cout << "<rquad>0.0</rquad>" << endl;
1410       cout << "<mesh_spacing>" << mesh_spacing << "</mesh_spacing>" << endl;
1411 
1412       cout.setf(ios::scientific,ios::floatfield);
1413       if ( upf_nlcc_flag == "T" )
1414       {
1415         cout << "<core_density size=\"" << nplin << "\">" << endl;
1416         for ( int i = 0; i < nplin; i++ )
1417           cout << setprecision(10) << nlcc_lin[i] << endl;
1418         cout << "</core_density>" << endl;
1419       }
1420 
1421       for ( int l = 0; l <= qso_lmax; l++ )
1422       {
1423         cout << "<projector l=\"" << l << "\" size=\"" << nplin << "\">"
1424              << endl;
1425         cout << "<radial_potential>" << endl;
1426         if ( iproj[l] == -1 )
1427         {
1428           // l == llocal
1429           for ( int i = 0; i < nplin; i++ )
1430             cout << setprecision(10) << vloc_lin[i] << endl;
1431         }
1432         else
1433         {
1434           for ( int i = 0; i < nplin; i++ )
1435             cout << setprecision(10) << vps_lin[iproj[l]][i] << endl;
1436         }
1437         cout << "</radial_potential>" << endl;
1438         // find index j corresponding to angular momentum l
1439         int j = 0;
1440         while ( upf_wf_l[j] != l && j < upf_nwf ) j++;
1441         // check if found
1442         const bool found = ( j != upf_nwf );
1443         // print wf only if found
1444         if ( found )
1445         {
1446           cout << "<radial_function>" << endl;
1447           for ( int i = 0; i < nplin; i++ )
1448             cout << setprecision(10) << wf_lin[j][i] << endl;
1449           cout << "</radial_function>" << endl;
1450         }
1451         cout << "</projector>" << endl;
1452       }
1453       cout << "</norm_conserving_pseudopotential>" << endl;
1454       cout << "</fpmd:species>" << endl;
1455     } // if SL
1456 
1457     if ( pseudo_type == "NC" )
1458     {
1459       // NLCC
1460       vector<double> upf_nlcc;
1461       if ( upf_nlcc_flag == "T" )
1462       {
1463         find_start_element("PP_NLCC");
1464         upf_nlcc.resize(upf_mesh_size);
1465         for ( int i = 0; i < upf_mesh_size; i++ )
1466           cin >> upf_nlcc[i];
1467         find_end_element("PP_NLCC");
1468       }
1469 
1470       cerr << " NC potential" << endl;
1471       // output original data in file upf.dat
1472       ofstream upf("upf.dat");
1473       upf << "# vloc" << endl;
1474       for ( int i = 0; i < upf_vloc.size(); i++ )
1475         upf << upf_r[i] << " " << upf_vloc[i] << endl;
1476       upf << endl << endl;
1477       for ( int j = 0; j < upf_nproj; j++ )
1478       {
1479         upf << "# proj j=" << j << endl;
1480         for ( int i = 0; i < upf_vnl[j].size(); i++ )
1481           upf << upf_r[i] << " " << upf_vnl[j][i] << endl;
1482         upf << endl << endl;
1483       }
1484 
1485       upf << "# dij " << endl;
1486       for ( int j = 0; j < upf_d.size(); j++ )
1487       {
1488         upf << j << " " << upf_d[j] << endl;
1489       }
1490       upf.close();
1491 
1492       // print summary
1493       cerr << "PP_INFO:" << endl << upf_pp_info << endl;
1494       cerr << "Element: " << upf_symbol << endl;
1495       cerr << "NLCC: " << upf_nlcc_flag << endl;
1496       // cerr << "XC: " << upf_xcf[0] << " " << upf_xcf[1] << " "
1497       //      << upf_xcf[2] << " " << upf_xcf[3] << endl;
1498       cerr << "Zv: " << upf_zval << endl;
1499       cerr << "lmax: " << qso_lmax << endl;
1500       cerr << "nproj: " << upf_nproj << endl;
1501       cerr << "mesh_size: " << upf_mesh_size << endl;
1502 
1503       // interpolate functions on linear mesh
1504       const double mesh_spacing = 0.01;
1505       int nplin = (int) (rcut / mesh_spacing);
1506       vector<double> f(upf_mesh_size), fspl(upf_mesh_size);
1507 
1508       // interpolate NLCC
1509       vector<double> nlcc_lin(nplin);
1510       if ( upf_nlcc_flag == "T" )
1511       {
1512         assert(upf_mesh_size==upf_nlcc.size());
1513         for ( int i = 0; i < upf_nlcc.size(); i++ )
1514           f[i] = upf_nlcc[i];
1515         int n = upf_nlcc.size();
1516         int bcnat_left = 0;
1517         double yp_left = 0.0;
1518         int bcnat_right = 1;
1519         double yp_right = 0.0;
1520         spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1521                bcnat_left,bcnat_right,&fspl[0]);
1522 
1523         for ( int i = 0; i < nplin; i++ )
1524         {
1525           double r = i * mesh_spacing;
1526           if ( r >= upf_r[0] )
1527             splint(n,&upf_r[0],&f[0],&fspl[0],r,&nlcc_lin[i]);
1528           else
1529             // use value closest to the origin for r=0
1530             nlcc_lin[i] = upf_nlcc[0];
1531           if ( fabs(nlcc_lin[i]) < 1.e-12 )
1532             nlcc_lin[i] = 0.0;
1533         }
1534       }
1535 
1536       // interpolate vloc
1537       // factor 0.5: convert from Ry in UPF to Hartree in QSO
1538       for ( int i = 0; i < upf_vloc.size(); i++ )
1539         f[i] = 0.5 * upf_vloc[i];
1540 
1541       int n = upf_vloc.size();
1542       int bcnat_left = 0;
1543       double yp_left = 0.0;
1544       int bcnat_right = 1;
1545       double yp_right = 0.0;
1546       spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1547              bcnat_left,bcnat_right,&fspl[0]);
1548 
1549       vector<double> vloc_lin(nplin);
1550       for ( int i = 0; i < nplin; i++ )
1551       {
1552         double r = i * mesh_spacing;
1553         if ( r >= upf_r[0] )
1554           splint(n,&upf_r[0],&f[0],&fspl[0],r,&vloc_lin[i]);
1555         else
1556           // use value closest to the origin for r=0
1557           vloc_lin[i] = 0.5 * upf_vloc[0];
1558       }
1559 
1560       // interpolate vnl[j], j=0, nproj-1
1561       vector<vector<double> > vnl_lin;
1562       vnl_lin.resize(upf_nproj);
1563       for ( int j = 0; j < vnl_lin.size(); j++ )
1564       {
1565         vnl_lin[j].resize(nplin);
1566       }
1567 
1568       for ( int j = 0; j < upf_nproj; j++ )
1569       {
1570         // interpolate projectors
1571         // note: upf_vnl contains r*projector
1572         // See UPF documentation at http://www.quantum-espresso.org/
1573         //   pseudopotentials/unified-pseudopotential-format
1574         assert(f.size()>=upf_vnl[j].size());
1575         for ( int i = 0; i < upf_vnl[j].size(); i++ )
1576           f[i] = upf_vnl[j][i];
1577 
1578         int n = f.size();
1579         int bcnat_left = 1;
1580         double yp_left = 0.0;
1581         int bcnat_right = 1;
1582         double yp_right = 0.0;
1583         spline(n,&upf_r[0],&f[0],yp_left,yp_right,
1584                bcnat_left,bcnat_right,&fspl[0]);
1585 
1586         for ( int i = 0; i < nplin; i++ )
1587         {
1588           double r = i * mesh_spacing;
1589           if ( r >= upf_r[0] )
1590             splint(n,&upf_r[0],&f[0],&fspl[0],r,&vnl_lin[j][i]);
1591           else
1592             vnl_lin[j][i] = upf_vnl[j][0];
1593           if ( fabs(vnl_lin[j][i]) < 1.e-12 )
1594             vnl_lin[j][i] = 0.0;
1595         }
1596       }
1597 
1598       // write local potential and projectors in gnuplot format on file vlin.dat
1599       ofstream vlin("vlin.dat");
1600       vlin << "# vlocal" << endl;
1601       for ( int i = 0; i < nplin; i++ )
1602         vlin << vloc_lin[i] << endl;
1603       vlin << endl << endl;
1604       for ( int iproj = 0; iproj < vnl_lin.size(); iproj++ )
1605       {
1606         vlin << "# projector, l=" << upf_proj_l[iproj] << endl;
1607         for ( int i = 0; i < nplin; i++ )
1608           vlin << i*mesh_spacing << " " << vnl_lin[iproj][i] << endl;
1609         vlin << endl << endl;
1610       }
1611 
1612       // Generate QSO file
1613 
1614       // output potential in QSO format
1615       cout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
1616       cout << "<fpmd:species xmlns:fpmd=\"http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0\"" << endl;
1617       cout << "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << endl;
1618       cout << "  xsi:schemaLocation=\"http://www.quantum-simulation.org/ns/fpmd/fpmd-1.0"  << endl;
1619       cout << "  species.xsd\">" << endl;
1620       cout << "<description>" << endl;
1621       cout << "Translated from UPF format by upf2qso " << release
1622            << " on " << isodate() << endl;
1623       cout << upf_pp_info;
1624       cout << "</description>" << endl;
1625       cout << "<symbol>" << upf_symbol << "</symbol>" << endl;
1626       cout << "<atomic_number>" << atomic_number << "</atomic_number>" << endl;
1627       cout << "<mass>" << mass << "</mass>" << endl;
1628       cout << "<norm_conserving_semilocal_pseudopotential>" << endl;
1629       cout << "<valence_charge>" << upf_zval << "</valence_charge>" << endl;
1630       cout << "<mesh_spacing>" << mesh_spacing << "</mesh_spacing>" << endl;
1631 
1632       cout.setf(ios::scientific,ios::floatfield);
1633       if ( upf_nlcc_flag == "T" )
1634       {
1635         cout << "<core_density size=\"" << nplin << "\">" << endl;
1636         for ( int i = 0; i < nplin; i++ )
1637           cout << setprecision(10) << nlcc_lin[i] << endl;
1638         cout << "</core_density>" << endl;
1639       }
1640 
1641       // local potential
1642       cout << "<local_potential size=\"" << nplin << "\">" << endl;
1643       for ( int i = 0; i < nplin; i++ )
1644         cout << setprecision(10) << vloc_lin[i] << endl;
1645       cout << "</local_potential>" << endl;
1646 
1647       // projectors
1648       // note: vnl_lin contains r[i]*projector[i]
1649       int ip = 0;
1650       for ( int l = 0; l <= upf_lmax; l++ )
1651       {
1652         for ( int i = 0; i < nproj_l[l]; i++ )
1653         {
1654           cout << "<projector l=\"" << l << "\" i=\""
1655                << i+1 << "\" size=\"" << nplin << "\">"
1656                << endl;
1657           // value at r=0:
1658           // quadratic extrapolation of vnl_lin(r)/r to r=0 if l==0
1659           if ( l == 0 )
1660           {
1661             // use quadratic extrapolation to zero
1662             const double h = mesh_spacing;
1663             const double v = (4.0/3.0)*vnl_lin[ip][1]/h -
1664                              (1.0/3.0)*vnl_lin[ip][2]/(2*h);
1665             cout << setprecision(10) << v << endl;
1666           }
1667           else
1668           {
1669             cout << setprecision(10) << 0.0 << endl;
1670           }
1671           for ( int j = 1; j < nplin; j++ )
1672           {
1673             const double r = j * mesh_spacing;
1674             cout << setprecision(10) << vnl_lin[ip][j]/r << endl;
1675           }
1676           ip++;
1677           cout << "</projector>" << endl;
1678         }
1679       }
1680 
1681       // d_ij
1682       int ibase = 0;
1683       int jbase = 0;
1684       for ( int l = 0; l <= upf_lmax; l++ )
1685       {
1686         for ( int i = 0; i < upf_nproj; i++ )
1687           for ( int j = 0; j < upf_nproj; j++ )
1688           {
1689             if ( (upf_proj_l[i] == l) && (upf_proj_l[j] == l) )
1690             {
1691               int ij = i + j*upf_nproj;
1692               cout << "<d_ij l=\"" << l << "\""
1693                    << " i=\"" << i-ibase+1 << "\" j=\"" << j-jbase+1
1694                    << "\"> " << setprecision(10) << 0.5*upf_d[ij] << " </d_ij>"
1695                    << endl;
1696             }
1697           }
1698         ibase += nproj_l[l];
1699         jbase += nproj_l[l];
1700       }
1701 
1702       cout << "</norm_conserving_semilocal_pseudopotential>" << endl;
1703       cout << "</fpmd:species>" << endl;
1704     }
1705   } // version 1 or 2
1706   return 0;
1707 }
1708