QMCPACK
WriteEshdf.cpp
Go to the documentation of this file.
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 ) 2018 QMCPACK developers
6 //
7 // File developed by : Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
8 //
9 // File created by : Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
10 /////////////////////////////////////////////////////////////////////////////////////////
11 
12 #include "WriteEshdf.h"
13 #include "XmlRep.h"
14 #include "FftContainer.h"
15 #include <sstream>
16 #include <map>
17 using namespace std;
18 //using namespace hdfhelper;
19 using namespace qmcplusplus;
20 
21 class KPoint
22 {
23 public:
24  double kx;
25  double ky;
26  double kz;
28  {
29  kx = 0;
30  ky = 0;
31  kz = 0;
32  }
33  KPoint(double x, double y, double z)
34  {
35  kx = x;
36  ky = y;
37  kz = z;
38  }
39  KPoint(const KPoint& kp)
40  {
41  kx = kp.kx;
42  ky = kp.ky;
43  kz = kp.kz;
44  }
45  KPoint& operator=(const KPoint& kp)
46  {
47  kx = kp.kx;
48  ky = kp.ky;
49  kz = kp.kz;
50  return *this;
51  }
52  bool operator==(const KPoint& kp) const
53  {
54  if ((std::abs(kx - kp.kx) < 1e-7) && (std::abs(ky - kp.ky) < 1e-7) && (std::abs(kz - kp.kz) < 1e-7))
55  {
56  return true;
57  }
58  return false;
59  }
60  bool operator<(const KPoint& kp) const
61  {
62  if (abs(kx - kp.kx) > 1e-7)
63  {
64  return kx < kp.kx;
65  }
66  else if (abs(ky - kp.ky) > 1e-7)
67  {
68  return ky < kp.ky;
69  }
70  else if (abs(kz - kp.kz) > 1e-7)
71  {
72  return kz < kp.kz;
73  }
74  return false;
75  }
76 };
77 
78 
79 EshdfFile::EshdfFile(const string& hdfFileName) { outfile_.create(hdfFileName); }
80 
81 EshdfFile::~EshdfFile() { outfile_.close(); }
82 
83 
84 int EshdfFile::wrapped(int i, int size) const
85 {
86  if (i < size / 2)
87  {
88  return i;
89  }
90  else
91  {
92  return wrapped(i - size, size);
93  }
94 }
95 
96 double EshdfFile::getOccupation(const XmlNode* nd) const
97 {
98  double result = 0.0;
99  vector<double> occupancies;
100  const XmlNode& densMat = nd->getChild("density_matrix");
101  densMat.getValue(occupancies);
102  for (int i = 0; i < occupancies.size(); i++)
103  {
104  result += occupancies[i];
105  }
106  return result;
107 }
108 
109 // before you enter here, better be in the a spin group of the hdf file
110 void EshdfFile::handleSpinGroup(const XmlNode* nd, double& nocc, FftContainer& cont)
111 {
112  nocc = getOccupation(nd);
113  int stateCounter = 0;
114  vector<double> eigvals;
115 
116  for (int chIdx = 0; chIdx < nd->getNumChildren(); chIdx++)
117  {
118  if (nd->getChild(chIdx).getName() == "grid_function")
119  {
120  //cout << "Working on state " << stateCounter << endl;
121  stringstream statess;
122  statess << "state_" << stateCounter;
123  outfile_.push(statess.str());
124 
125  // HACK_HACK_HACK!!!
126  // QBOX does not write out the eigenvalues for the states in the
127  // sample file, so just make sure they are treated in ascending order
128  eigvals.push_back(-5000.0 + stateCounter);
129 
130  const XmlNode& eigFcnNode = nd->getChild(chIdx);
131  readInEigFcn(eigFcnNode, cont);
132  // write eigfcn to proper place
133  array<int, 2> psig_dims{cont.fullSize, 2};
134 
135  vector<double> temp;
136  for (int i = 0; i < cont.fullSize; i++)
137  {
138  temp.push_back(cont.kspace[i][0]);
139  temp.push_back(cont.kspace[i][1]);
140  }
141 
142  outfile_.writeSlabReshaped(temp, psig_dims, "psi_g");
143  stateCounter++;
144  outfile_.pop();
145  }
146  }
147 
148  outfile_.write(stateCounter, "number_of_states");
149  outfile_.write(eigvals, "eigenvalues");
150 }
151 
153 {
154  const string type = nd.getAttribute("type");
155  const string encoding = nd.getAttribute("encoding");
156 
157  if (encoding != "text")
158  {
159  cerr << "Don't yet know how to handle encoding of wavefunction values other than text" << endl;
160  exit(1);
161  }
162 
163  vector<double> values;
164  nd.getValue(values);
165  const double fixnorm = 1 / std::sqrt(static_cast<double>(cont.fullSize));
166  if (type == "complex")
167  {
168  int index = 0;
169  for (int ix = 0; ix < cont.getNx(); ix++)
170  {
171  for (int iy = 0; iy < cont.getNy(); iy++)
172  {
173  for (int iz = 0; iz < cont.getNz(); iz++)
174  {
175  const int qbx = cont.getQboxIndex(ix, iy, iz);
176  cont.rspace[index][0] = values[2 * qbx] * fixnorm;
177  cont.rspace[index][1] = values[2 * qbx + 1] * fixnorm;
178  index++;
179  }
180  }
181  }
182  }
183  else if (type == "double")
184  {
185  int index = 0;
186  for (int ix = 0; ix < cont.getNx(); ix++)
187  {
188  for (int iy = 0; iy < cont.getNy(); iy++)
189  {
190  for (int iz = 0; iz < cont.getNz(); iz++)
191  {
192  const int qbx = cont.getQboxIndex(ix, iy, iz);
193  cont.rspace[index][0] = values[qbx] * fixnorm;
194  cont.rspace[index][1] = 0.0;
195  index++;
196  }
197  }
198  }
199  }
200  //cout << "in readInEigFcn, before fft, real space L2 norm = " << cont.getL2NormRS() << endl;
201  cont.executeFFT();
202  cont.fixKsNorm(fixnorm);
203  //cout << "in readInEigFcn, after fft, k space L2 norm = " << cont.getL2NormKS() << endl;
204 }
205 
206 void EshdfFile::writeApplication(const string& appName, int major, int minor, int sub)
207 {
208  vector<int> version{major, minor, sub};
209 
210  outfile_.push("application");
211  string str = appName;
212  outfile_.write(str, "code");
213  outfile_.write(version, "version");
214  outfile_.pop();
215 }
216 
217 
219 {
220  vector<int> version{2, 1, 0};
221  outfile_.write(version, "version");
222 }
223 
225 {
226  vector<int> version{0, 1, 0};
227  outfile_.push("creator");
228  string tmp_str = "convertpw4qmc";
229  outfile_.write(tmp_str, "program_name");
230  outfile_.write(version, "version");
231  outfile_.pop();
232 }
233 
235 {
236  string tmp_str = "ES-HDF";
237  outfile_.write(tmp_str, "format");
238 }
239 
241 {
242  const string appName = "qbox";
243  const XmlNode& description = qboxSample.getChild("description");
244  string desString = description.getValue();
245  int versionStart = desString.find("qbox-");
246  versionStart += 5;
247  string versionStr = desString.substr(versionStart);
248 
249  const int firstDotIdx = versionStr.find_first_of('.');
250  const int secondDotIdx = versionStr.find_last_of('.');
251  const int major = stoi(versionStr.substr(0, firstDotIdx));
252  const int minor = stoi(versionStr.substr(firstDotIdx + 1, secondDotIdx - firstDotIdx - 1));
253  const int sub = stoi(versionStr.substr(secondDotIdx + 1));
254 
255  writeApplication(appName, major, minor, sub);
256  writeVersion();
257  writeCreator();
258  writeFormat();
259 }
260 
261 int EshdfFile::getIntsOnly(const string& str) const
262 {
263  stringstream numerals;
264  int temp;
265  for (int i = 0; i < str.size(); ++i)
266  {
267  string blah = str.substr(i, 1);
268  if (stringstream(blah) >> temp)
269  {
270  numerals << str[i];
271  }
272  }
273  int result;
274  numerals >> result;
275  return result;
276 }
277 
278 
280 {
281  const string appName = "espresso";
282  const XmlNode& creatorNode = qeXml.getChild("general_info").getChild("creator");
283  const string versionStr = creatorNode.getAttribute("VERSION");
284  int minor = 0;
285  int sub = 0;
286  const int firstDotIdx = versionStr.find_first_of('.');
287  const int secondDotIdx = versionStr.find_last_of('.');
288  const int major = getIntsOnly(versionStr.substr(0, firstDotIdx));
289  if (firstDotIdx == secondDotIdx) // this means on subersion is provided
290  {
291  minor = getIntsOnly(versionStr.substr(firstDotIdx + 1));
292  }
293  else
294  {
295  minor = getIntsOnly(versionStr.substr(firstDotIdx + 1, secondDotIdx - firstDotIdx - 1));
296  sub = getIntsOnly(versionStr.substr(secondDotIdx + 1));
297  }
298  writeApplication(appName, major, minor, sub);
299  writeVersion();
300  writeCreator();
301  writeFormat();
302 }
303 
304 void EshdfFile::writeQboxSupercell(const XmlNode& qboxSample)
305 {
306  // grab the primitive translation vectors from the atomset tag's attributes and put the entries in the vector ptvs
307  const XmlNode& atomset = qboxSample.getChild("atomset");
308  const XmlNode& unit_cell = atomset.getChild("unit_cell");
309 
310  stringstream ss;
311  ss << unit_cell.getAttribute("a") << " " << unit_cell.getAttribute("b") << " " << unit_cell.getAttribute("c");
312 
313  vector<double> ptvs;
314  double temp;
315  while (ss >> temp)
316  {
317  ptvs.push_back(temp);
318  }
319 
320  // write the ptvs to the supercell group of the hdf file
321  array<int, 2> dims{3, 3};
322  outfile_.push("supercell");
323  outfile_.writeSlabReshaped(ptvs, dims, "primitive_vectors");
324  outfile_.pop();
325 }
326 
328 {
329  // grab the primitive translation vectors the output tag's atomic structure part
330  const XmlNode& cell = qeXml.getChild("output").getChild("atomic_structure").getChild("cell");
331  const XmlNode& a = cell.getChild("a1");
332  const XmlNode& b = cell.getChild("a2");
333  const XmlNode& c = cell.getChild("a3");
334 
335  stringstream ss;
336  ss << a.getValue() << " " << b.getValue() << " " << c.getValue();
337 
338  vector<double> ptvs;
339  double temp;
340  while (ss >> temp)
341  {
342  ptvs.push_back(temp);
343  }
344 
345  // write the ptvs to the supercell group of the hdf file
346  array<int, 2> dims{3, 3};
347  outfile_.push("supercell");
348  outfile_.writeSlabReshaped(ptvs, dims, "primitive_vectors");
349  outfile_.pop();
350 }
351 
353 {
354  const XmlNode& atomic_species_xml = qeXml.getChild("output").getChild("atomic_species");
355 
356  //make group
357  outfile_.push("atoms");
358 
359  map<string, int> species_name_to_int;
360  //go through each species, extract:
361  // name, mass
362  // in future, it would be good to extract atomic_number, and valence_charge
363  // then write to a file, also set up mapping between species name and number
364 
365  int species_num = 0;
366  for (int i = 0; i < atomic_species_xml.getNumChildren(); i++)
367  {
368  if (atomic_species_xml.getChild(i).getName() == "species")
369  {
370  const XmlNode& species_xml = atomic_species_xml.getChild(i);
371  string sp_name = species_xml.getAttribute("name");
372  species_name_to_int[sp_name] = species_num;
373  double mass;
374  species_xml.getChild("mass").getValue(mass);
375 
376  stringstream gname;
377  gname << "species_" << species_num;
378  outfile_.push(gname.str());
379  outfile_.write(sp_name, "name");
380  outfile_.write(mass, "mass");
381  species_num++;
382  outfile_.pop();
383  }
384  }
385  outfile_.write(species_num, "number_of_species");
386 
387  const XmlNode& atomic_positions_xml =
388  qeXml.getChild("output").getChild("atomic_structure").getChild("atomic_positions");
389  // go through atoms and extract their position and type
390  std::vector<int> species_ids;
391  std::vector<double> positions;
392  int at_num = 0;
393  for (int i = 0; i < atomic_positions_xml.getNumChildren(); i++)
394  {
395  if (atomic_positions_xml.getChild(i).getName() == "atom")
396  {
397  const XmlNode& at_node_xml = atomic_positions_xml.getChild(i);
398  species_ids.push_back(species_name_to_int[at_node_xml.getAttribute("name")]);
399  at_node_xml.getValue(positions); // this will append the three numbers to the verctor
400  at_num++;
401  }
402  }
403  array<int, 2> dims{at_num, 3};
404  outfile_.writeSlabReshaped(positions, dims, "positions");
405  outfile_.write(species_ids, "species_ids");
406  outfile_.write(at_num, "number_of_atoms");
407 
408  outfile_.pop();
409 }
410 
411 
412 void EshdfFile::writeQboxAtoms(const XmlNode& qboxSample)
413 {
414  const XmlNode& atomset = qboxSample.getChild("atomset");
415 
416  //make group
417  outfile_.push("atoms");
418 
419  map<string, int> SpeciesNameToInt;
420  //go through each species, extract:
421  // atomic_number, mass, name, pseudopotential and valence_charge
422  // then write to a file, also set up mapping between species name and number
423  int speciesNum = 0;
424  for (int i = 0; i < atomset.getNumChildren(); i++)
425  {
426  if (atomset.getChild(i).getName() == "species")
427  {
428  const XmlNode& species = atomset.getChild(i);
429 
430  string spName = species.getAttribute("name");
431  SpeciesNameToInt[spName] = speciesNum;
432 
433  int atomic_number;
434  species.getChild("atomic_number").getValue(atomic_number);
435  double mass;
436  species.getChild("mass").getValue(mass);
437  string name = species.getChild("symbol").getValue();
438  int val_charge;
439  species.getChild("norm_conserving_pseudopotential").getChild("valence_charge").getValue(val_charge);
440 
441  stringstream gname;
442  gname << "species_" << speciesNum;
443  outfile_.push(gname.str());
444  outfile_.write(atomic_number, "atomic_number");
445  outfile_.write(mass, "mass");
446  outfile_.write(val_charge, "valence_charge");
447  outfile_.write(name, "name");
448  string tmp_str = "unknown";
449  outfile_.write(tmp_str, "pseudopotential");
450  speciesNum++;
451  outfile_.pop();
452  }
453  }
454  outfile_.write(speciesNum, "number_of_species");
455 
456  // go through atoms and extract their position and type
457  std::vector<int> species_ids;
458  std::vector<double> positions;
459  int at_num = 0;
460  for (int i = 0; i < atomset.getNumChildren(); i++)
461  {
462  if (atomset.getChild(i).getName() == "atom")
463  {
464  const XmlNode& atNode = atomset.getChild(i);
465  species_ids.push_back(SpeciesNameToInt[atNode.getAttribute("species")]);
466  atNode.getChild("position").getValue(positions);
467  at_num++;
468  }
469  }
470  array<int, 2> dims{at_num, 3};
471  outfile_.writeSlabReshaped(positions, dims, "positions");
472  outfile_.write(species_ids, "species_ids");
473  outfile_.write(at_num, "number_of_atoms");
474  outfile_.pop();
475 }
476 
478 {
479  hdf_archive file;
480  bool result = file.open(fname);
481  if (!result)
482  {
483  cout << "could not find " << fname << ", make sure espresso is" << endl;
484  cout << "compiled with hdf support and you do not explicitly set" << endl;
485  cout << "wf_collect=.false. in your input" << endl;
486  exit(1);
487  }
488  return file;
489 }
490 
491 // need to be in the electrons group when entering this
492 void EshdfFile::handleDensity(const XmlNode& qeXml, const string& dir_name, int spinpol)
493 {
494  const XmlNode& output_xml = qeXml.getChild("output");
495  // read in the grid to put in the charge density
496  const XmlNode& basis_set_xml = output_xml.getChild("basis_set");
497  const XmlNode& fft_grid = basis_set_xml.getChild("fft_grid");
498  int nr1;
499  int nr2;
500  int nr3;
501  fft_grid.getAttribute("nr1", nr1);
502  fft_grid.getAttribute("nr2", nr2);
503  fft_grid.getAttribute("nr3", nr3);
504  // also figure out how many gvectors there will be
505  const XmlNode& ngm_xml = basis_set_xml.getChild("ngm");
506  int num_dens_gvecs;
507  ngm_xml.getValue(num_dens_gvecs);
508 
509  // now open the hdf file and read the necessary quantities
510  const string dens_fname = dir_name + "charge-density.hdf5";
511  hdf_archive densfile = openHdfFileForRead(dens_fname);
512 
513  vector<int> readDims;
514  densfile.getShape<int>("MillerIndices", readDims);
515  vector<int> gvecs;
516  array<int, 2> shape{readDims[0], readDims[1]};
517  densfile.readSlabReshaped(gvecs, shape, "MillerIndices");
518 
519  vector<double> dens;
520  densfile.read(dens, "rhotot_g");
521 
522  vector<double> diffdens;
523  if (spinpol == 1)
524  {
525  densfile.read(diffdens, "rhodiff_g");
526  }
527 
528  // now need to write everything out
529  outfile_.push("density");
530  array<int, 2> dims{num_dens_gvecs, 3};
531  outfile_.writeSlabReshaped(gvecs, dims, "gvectors");
532 
533  vector<int> grid{nr1, nr2, nr3};
534  outfile_.write(grid, "mesh");
535  outfile_.write(num_dens_gvecs, "number_of_gvectors");
536 
537  array<int, 2> dims_dens{num_dens_gvecs, 2};
538  if (spinpol == 0)
539  {
540  outfile_.push("spin_0");
541  outfile_.writeSlabReshaped(dens, dims_dens, "density_g");
542  outfile_.pop();
543  }
544  else
545  {
546  // do spin up
547  vector<double> working(2 * num_dens_gvecs);
548  for (int i = 0; i < num_dens_gvecs * 2; i++)
549  {
550  working[i] = (dens[i] + diffdens[i]) / 2.0;
551  }
552  outfile_.push("spin_0");
553  outfile_.writeSlabReshaped(working, dims_dens, "density_g");
554  outfile_.pop();
555 
556  // do spin down
557  for (int i = 0; i < num_dens_gvecs * 2; i++)
558  {
559  working[i] = (dens[i] - diffdens[i]) / 2.0;
560  }
561  outfile_.push("spin_1");
562  outfile_.writeSlabReshaped(working, dims_dens, "density_g");
563  outfile_.pop();
564  }
565  outfile_.pop(); // get out of density group
566 }
567 
568 void EshdfFile::processKPts(const XmlNode& band_structure_xml,
569  const vector<double>& ptvs,
570  vector<vector<double>>& eigenvals,
571  vector<vector<double>>& occupations,
572  vector<KPoint>& kpts,
573  vector<double>& weights,
574  vector<int>& ngvecs)
575 {
576  for (int i = 0; i < band_structure_xml.getNumChildren(); i++)
577  {
578  const XmlNode& child_xml = band_structure_xml.getChild(i);
579  if (child_xml.getName() == "ks_energies")
580  {
581  vector<double> eigs;
582  vector<double> occs;
583  vector<double> kpt_vec;
584  KPoint kpt;
585  double weight;
586  int ngvec;
587 
588  const XmlNode& k_point_xml = child_xml.getChild("k_point");
589  k_point_xml.getAttribute("weight", weight);
590  k_point_xml.getValue(kpt_vec);
591  kpt.kx = kpt_vec[0] * ptvs[0] + kpt_vec[1] * ptvs[1] + kpt_vec[2] * ptvs[2];
592  kpt.ky = kpt_vec[0] * ptvs[3] + kpt_vec[1] * ptvs[4] + kpt_vec[2] * ptvs[5];
593  kpt.kz = kpt_vec[0] * ptvs[6] + kpt_vec[1] * ptvs[7] + kpt_vec[2] * ptvs[8];
594 
595  child_xml.getChild("npw").getValue(ngvec);
596  child_xml.getChild("eigenvalues").getValue(eigs);
597  child_xml.getChild("occupations").getValue(occs);
598 
599  eigenvals.push_back(eigs);
600  occupations.push_back(occs);
601  kpts.push_back(kpt);
602  weights.push_back(weight);
603  ngvecs.push_back(ngvec);
604  }
605  }
606 }
607 
608 void EshdfFile::getNumElectrons(vector<vector<double>>& occupations,
609  vector<double>& weights,
610  int& nup,
611  int& ndn,
612  int spinpol,
613  int noncol)
614 {
615  nup = 0;
616  ndn = 0;
617 
618  double nup_flt = 0.0;
619  double ndn_flt = 0.0;
620 
621  for (int i = 0; i < weights.size(); i++)
622  {
623  if (noncol == 1)
624  {
625  double sum = 0.0;
626  for (int j = 0; j < occupations[i].size(); j++)
627  {
628  sum += occupations[i][j];
629  }
630  nup_flt += sum * weights[i];
631  ndn_flt = -1.0;
632  }
633  else if (spinpol == 0)
634  {
635  double sum = 0.0;
636  for (int j = 0; j < occupations[i].size(); j++)
637  {
638  sum += occupations[i][j];
639  }
640  nup_flt += sum * weights[i] / 2.0;
641  ndn_flt += sum * weights[i] / 2.0;
642  }
643  else
644  {
645  double sum_up = 0.0;
646  double sum_dn = 0.0;
647  for (int j = 0; j < occupations[i].size() / 2; j++)
648  {
649  sum_up += occupations[i][j];
650  sum_dn += occupations[i][j + occupations[i].size() / 2];
651  }
652  nup_flt += sum_up * weights[i];
653  ndn_flt += sum_dn * weights[i];
654  }
655  }
656  nup = static_cast<int>(round(nup_flt));
657  ndn = static_cast<int>(round(ndn_flt));
658 }
659 
660 vector<double> EshdfFile::getPtvs(const XmlNode& qeXml)
661 {
662  const XmlNode& reciprocal_lattice_xml = qeXml.getChild("output").getChild("basis_set").getChild("reciprocal_lattice");
663  vector<double> rlv; // reciprocal_lattice_vectors
664  reciprocal_lattice_xml.getChild("b1").getValue(rlv);
665  reciprocal_lattice_xml.getChild("b2").getValue(rlv);
666  reciprocal_lattice_xml.getChild("b3").getValue(rlv);
667 
668  const double det = rlv[0] * (rlv[4] * rlv[8] - rlv[5] * rlv[7]) - rlv[1] * (rlv[3] * rlv[8] - rlv[5] * rlv[6]) +
669  rlv[2] * (rlv[3] * rlv[7] - rlv[4] * rlv[6]);
670  const double invdet = 1.0 / det;
671  vector<double> ptv;
672  ptv.push_back(invdet * (rlv[4] * rlv[8] - rlv[5] * rlv[7]));
673  ptv.push_back(invdet * (rlv[5] * rlv[6] - rlv[3] * rlv[8]));
674  ptv.push_back(invdet * (rlv[3] * rlv[7] - rlv[4] * rlv[6]));
675  ptv.push_back(invdet * (rlv[2] * rlv[7] - rlv[1] * rlv[8]));
676  ptv.push_back(invdet * (rlv[0] * rlv[8] - rlv[2] * rlv[6]));
677  ptv.push_back(invdet * (rlv[1] * rlv[6] - rlv[0] * rlv[7]));
678  ptv.push_back(invdet * (rlv[1] * rlv[5] - rlv[2] * rlv[4]));
679  ptv.push_back(invdet * (rlv[2] * rlv[3] - rlv[0] * rlv[5]));
680  ptv.push_back(invdet * (rlv[0] * rlv[4] - rlv[1] * rlv[3]));
681  return ptv;
682 }
683 
684 void EshdfFile::readKptGvecs(int kpt_num, const string& dir_name, int spinpol, momap_t& morefmap)
685 
686 {
687  stringstream ss;
688  string fname;
689  if (spinpol == 1)
690  ss << dir_name << "wfcup" << (kpt_num + 1) << ".hdf5";
691  else
692  ss << dir_name << "wfc" << (kpt_num + 1) << ".hdf5";
693  fname = ss.str();
694  hdf_archive wfc_file = openHdfFileForRead(fname);
695  vector<int> readShape;
696  wfc_file.getShape<int>("MillerIndices", readShape);
697  vector<int> gvecs;
698  array<int, 2> shape{readShape[0], readShape[1]};
699  wfc_file.readSlabReshaped(gvecs, shape, "MillerIndices");
700  wfc_file.close();
701 
702  for (int i = 0; i < readShape[0]; i++)
703  {
704  vector<int> gv;
705  for (int d = 0; d < readShape[1]; d++)
706  gv.push_back(gvecs[i * readShape[1] + d]);
707  mopair_t p(gv, std::complex<double>(0, 0));
708  morefmap.insert(p);
709  }
710 }
711 
712 // should already be in the electrons group when you call this
713 void EshdfFile::handleKpt(int kpt_num,
714  const std::string& dir_name,
715  KPoint& kpt,
716  const std::vector<double>& eigenvalues,
717  double weight,
718  int spinpol,
719  int noncol,
720  const momap_t& moref)
721 {
722  stringstream ss;
723  ss << "kpoint_" << kpt_num;
724  outfile_.push(ss.str());
725  outfile_.write(weight, "weight");
726 
727  vector<double> kpt_vector{kpt.kx, kpt.ky, kpt.kz};
728  outfile_.write(kpt_vector, "reduced_k");
729 
730  //reread gvecs for this kpts to create a map to coeffs
731  //then will merge with the maximal gvec map in moref
732  //this will fill unused gvecs with zeros
733  string fname;
734  if (spinpol == 1)
735  {
736  stringstream ss;
737  ss << dir_name << "wfcup" << (kpt_num + 1) << ".hdf5";
738  fname = ss.str();
739  }
740  else
741  {
742  stringstream ss;
743  ss << dir_name << "wfc" << (kpt_num + 1) << ".hdf5";
744  fname = ss.str();
745  }
746  hdf_archive wfc_file = openHdfFileForRead(fname);
747  vector<int> readShape;
748  wfc_file.getShape<int>("MillerIndices", readShape);
749  vector<int> gvecs;
750  array<int, 2> shape{readShape[0], readShape[1]};
751  wfc_file.readSlabReshaped(gvecs, shape, "MillerIndices");
752  wfc_file.close();
753 
754  vector<vector<int>> gvs;
755  for (int i = 0; i < readShape[0]; i++)
756  {
757  vector<int> g;
758  for (int d = 0; d < readShape[1]; d++)
759  g.push_back(gvecs[i * readShape[1] + d]);
760  gvs.push_back(g);
761  }
762 
763  // now do the non-gvectors related stuff
764  hdf_archive spin_0_file;
765  hdf_archive spin_1_file;
766 
767  if (spinpol == 1)
768  {
769  stringstream ss0;
770  ss0 << dir_name << "wfcup" << (kpt_num + 1) << ".hdf5";
771  spin_0_file.open(ss0.str());
772  stringstream ss1;
773  ss1 << dir_name << "wfcdw" << (kpt_num + 1) << ".hdf5";
774  spin_1_file.open(ss1.str());
775  }
776  else
777  {
778  stringstream ss0;
779  ss0 << dir_name << "wfc" << (kpt_num + 1) << ".hdf5";
780  spin_0_file.open(ss0.str());
781  }
782 
783  // set up storage space for the coefficients to be read from the file
784  vector<double> upcoefs;
785  vector<double> dncoefs;
786  int ng = gvs.size();
787  if (spinpol == 0)
788  {
789  if (noncol == 0)
790  upcoefs.resize(ng * 2);
791  if (noncol == 1)
792  {
793  upcoefs.resize(ng * 4);
794  dncoefs.resize(ng * 2);
795  }
796  }
797  else
798  {
799  upcoefs.resize(ng * 2);
800  dncoefs.resize(ng * 2);
801  }
802 
803  vector<momap_t> states_up;
804  vector<momap_t> states_dn;
805  int states_to_loop = eigenvalues.size();
806  if (spinpol == 1)
807  states_to_loop /= 2;
808  for (int state = 0; state < states_to_loop; state++)
809  {
810  // set the elements of coefs to 0
811  for (int i = 0; i < upcoefs.size(); i++)
812  upcoefs[i] = 0.0;
813  for (int i = 0; i < dncoefs.size(); i++)
814  dncoefs[i] = 0.0;
815 
816  // do what is necessary to read only this band's coefficients
817  array<int, 2> read_from{state, -1};
818  if (spinpol == 0)
819  {
820  spin_0_file.readSlabSelection(upcoefs, read_from, "evc");
821  }
822  else
823  {
824  spin_0_file.readSlabSelection(upcoefs, read_from, "evc");
825  spin_1_file.readSlabSelection(dncoefs, read_from, "evc");
826  }
827 
828  if (spinpol == 0)
829  {
830  if (noncol == 0)
831  {
832  momap_t moup;
833  for (int i = 0; i < ng; i++)
834  {
835  complex<double> c(upcoefs[i * 2], upcoefs[i * 2 + 1]);
836  mopair_t p(gvs[i], c);
837  moup.insert(p);
838  }
839  //now fill in rest of gvecs with zeros
840  moup.insert(moref.begin(), moref.end());
841  states_up.push_back(moup);
842  }
843  else
844  {
845  //dn part of spinor in second half of upcoefs
846  for (int i = 0; i < ng * 2; i++)
847  dncoefs[i] = upcoefs[i + 2 * ng];
848  momap_t moup, modn;
849  for (int i = 0; i < ng; i++)
850  {
851  complex<double> c(upcoefs[i * 2], upcoefs[i * 2 + 1]);
852  mopair_t p(gvs[i], c);
853  moup.insert(p);
854  c = complex<double>(dncoefs[i * 2], dncoefs[i * 2 + 1]);
855  p = mopair_t(gvs[i], c);
856  modn.insert(p);
857  }
858  //now fill in rest of gvecs with zeros
859  moup.insert(moref.begin(), moref.end());
860  modn.insert(moref.begin(), moref.end());
861  states_up.push_back(moup);
862  states_dn.push_back(modn);
863  }
864  }
865  else
866  {
867  momap_t moup, modn;
868  for (int i = 0; i < ng; i++)
869  {
870  complex<double> c(upcoefs[i * 2], upcoefs[i * 2 + 1]);
871  mopair_t p(gvs[i], c);
872  moup.insert(p);
873  c = complex<double>(dncoefs[i * 2], dncoefs[i * 2 + 1]);
874  p = mopair_t(gvs[i], c);
875  modn.insert(p);
876  }
877  moup.insert(moref.begin(), moref.end());
878  modn.insert(moref.begin(), moref.end());
879  states_up.push_back(moup);
880  states_dn.push_back(modn);
881  }
882  }
883  spin_0_file.close();
884  spin_1_file.close();
885 
886  //now write to eshdf
887  if (kpt_num == 0)
888  {
889  vector<int> allgvs;
890  int nallgvs = moref.size();
891  int dim = moref.begin()->first.size();
892  array<int, 2> shape{nallgvs, dim};
893  for (auto& v : moref)
894  {
895  for (int d = 0; d < dim; d++)
896  allgvs.push_back(v.first[d]);
897  }
898  outfile_.writeSlabReshaped(allgvs, shape, "gvectors");
899  outfile_.write(nallgvs, "number_of_gvectors");
900  }
901 
902  for (int state = 0; state < states_up.size(); state++)
903  {
904  stringstream ss;
905  ss << "state_" << state;
906  outfile_.push("spin_0");
907  outfile_.push(ss.str());
908  vector<double> c;
909  for (auto& v : states_up[state])
910  {
911  c.push_back(v.second.real());
912  c.push_back(v.second.imag());
913  }
914  array<int, 2> dims{static_cast<int>(states_up[state].size()), 2};
915  outfile_.writeSlabReshaped(c, dims, "psi_g");
916  outfile_.pop();
917  outfile_.pop();
918  if (noncol == 1 || spinpol == 1)
919  {
920  outfile_.push("spin_1");
921  outfile_.push(ss.str());
922  vector<double> c;
923  for (auto& v : states_dn[state])
924  {
925  c.push_back(v.second.real());
926  c.push_back(v.second.imag());
927  }
928  array<int, 2> dims{static_cast<int>(states_dn[state].size()), 2};
929  outfile_.writeSlabReshaped(c, dims, "psi_g");
930  outfile_.pop();
931  outfile_.pop();
932  }
933  }
934 
935  // now all the states are written, so write out eigenvalues and number of states
936  vector<double> eigval = eigenvalues;
937  if (spinpol == 0)
938  {
939  outfile_.push("spin_0");
940  int int_eig_sz = static_cast<int>(eigenvalues.size());
941  outfile_.write(int_eig_sz, "number_of_states");
942  outfile_.write(eigval, "eigenvalues");
943  outfile_.pop();
944  if (noncol == 1)
945  {
946  outfile_.push("spin_1");
947  outfile_.write(int_eig_sz, "number_of_states");
948  outfile_.write(eigval, "eigenvalues");
949  outfile_.pop();
950  }
951  }
952  else // spin polarized case
953  {
954  int totstates = eigenvalues.size();
955  int upstates = totstates / 2;
956  int dnstates = totstates / 2;
957 
958  vector<double> upeig;
959  vector<double> dneig;
960  for (int i = 0; i < upstates; i++)
961  {
962  upeig.push_back(eigenvalues[i]);
963  dneig.push_back(eigenvalues[i + upstates]);
964  }
965 
966  outfile_.push("spin_0");
967  outfile_.write(upstates, "number_of_states");
968  outfile_.write(upeig, "eigenvalues");
969  outfile_.pop();
970 
971  outfile_.push("spin_1");
972  outfile_.write(dnstates, "number_of_states");
973  outfile_.write(dneig, "eigenvalues");
974  outfile_.pop();
975  }
976 
977  outfile_.pop(); // get out of the kpoint_ kpt_num group
978 }
979 
980 void EshdfFile::writeQEElectrons(const XmlNode& qeXml, const string& dir_name)
981 {
982  // make electrons group in hdf file
983  outfile_.push("electrons");
984  const XmlNode& output_xml = qeXml.getChild("output");
985 
986  // need to figure out if this is spin polarized, or if it is noncolinear
987  int spinpol = 0;
988  int noncol = 0;
989  const XmlNode& band_structure_xml = output_xml.getChild("band_structure");
990 
991  const XmlNode& lsda_xml = band_structure_xml.getChild("lsda");
992  string lsda_string_bool = lsda_xml.getValue();
993  const XmlNode& noncolin_xml = band_structure_xml.getChild("noncolin");
994  string noncolin_string_bool = noncolin_xml.getValue();
995  if (lsda_string_bool == "true")
996  spinpol = 1;
997  if (noncolin_string_bool == "true")
998  noncol = 1;
999 
1000  // scrape xml file and associated hdf for density and write out
1001  handleDensity(qeXml, dir_name, spinpol);
1002 
1003  // read in information about kpts from the xml
1004  vector<double> ptv = getPtvs(qeXml);
1005  vector<vector<double>> eigenvals;
1006  vector<vector<double>> occupations;
1007  vector<KPoint> kpts;
1008  vector<double> weights;
1009  vector<int> ngvecs;
1010  processKPts(band_structure_xml, ptv, eigenvals, occupations, kpts, weights, ngvecs);
1011 
1012  // write number of kpoints, number of spins and spinors if appropriate
1013  int int_kpt_sz = static_cast<int>(kpts.size());
1014  outfile_.write(int_kpt_sz, "number_of_kpoints");
1015  outfile_.write(noncol, "has_spinors");
1016 
1017  if (noncol == 0)
1018  {
1019  int nspins = 1;
1020  if (spinpol == 1)
1021  nspins = 2;
1022  outfile_.write(nspins, "number_of_spins");
1023  }
1024 
1025  // figure out how many electrons of each spin and write to file
1026  int nup;
1027  int ndn;
1028  getNumElectrons(occupations, weights, nup, ndn, spinpol, noncol);
1029  vector<int> nels;
1030  nels.push_back(nup);
1031  nels.push_back(ndn);
1032  outfile_.write(nels, "number_of_electrons");
1033 
1034  //find maximal set of gvecs
1035  momap_t moref;
1036  for (int i = 0; i < kpts.size(); i++)
1037  readKptGvecs(i, dir_name, spinpol, moref);
1038  //moref now has maximal set of gvecs
1039  for (int i = 0; i < kpts.size(); i++)
1040  handleKpt(i, dir_name, kpts[i], eigenvals[i], weights[i], spinpol, noncol, moref);
1041 }
1042 
1043 
1045 {
1046  const XmlNode& wfnNode = qboxSample.getChild("wavefunction");
1047  int nspin, nel;
1048  wfnNode.getAttribute("nspin", nspin);
1049  wfnNode.getAttribute("nel", nel);
1050  const XmlNode& gridNode = wfnNode.getChild("grid");
1051  int nx, ny, nz;
1052  gridNode.getAttribute("nx", nx);
1053  gridNode.getAttribute("ny", ny);
1054  gridNode.getAttribute("nz", nz);
1055 
1056  FftContainer fftCont(nx, ny, nz);
1057 
1058  vector<KPoint> kpts;
1059  map<KPoint, const XmlNode*> kptToUpNode;
1060  map<KPoint, const XmlNode*> kptToDnNode;
1061 
1062  for (int i = 0; i < wfnNode.getNumChildren(); i++)
1063  {
1064  if (wfnNode.getChild(i).getName() == "slater_determinant")
1065  {
1066  const XmlNode& sdNode = wfnNode.getChild(i);
1067  int spinIdx = sdNode.getAttributeIndex("spin");
1068  string species;
1069  if (spinIdx >= 0)
1070  {
1071  species = sdNode.getAttribute(spinIdx);
1072  }
1073  else
1074  {
1075  species = "up";
1076  }
1077 
1078  KPoint kpt;
1079  stringstream ss;
1080  ss.str(sdNode.getAttribute("kpoint"));
1081  ss >> kpt.kx;
1082  ss >> kpt.ky;
1083  ss >> kpt.kz;
1084 
1085  bool newKpt = true;
1086  for (int j = 0; j < kpts.size(); j++)
1087  {
1088  if (kpts[j] == kpt)
1089  {
1090  newKpt = false;
1091  }
1092  }
1093  if (newKpt)
1094  {
1095  kpts.push_back(kpt);
1096  }
1097 
1098  if (species == "up")
1099  {
1100  kptToUpNode[kpt] = std::addressof(sdNode);
1101  }
1102  else
1103  {
1104  kptToDnNode[kpt] = std::addressof(sdNode);
1105  }
1106  }
1107  }
1108  outfile_.push("electrons");
1109  if (kpts.size() > 1)
1110  {
1111  std::cout << "Warning: Due to limitations of the current tool, extreme care" << std::endl;
1112  std::cout << "is required if tiling to a supercell from qbox calculations with" << std::endl;
1113  std::cout << "multiple k-points. Specifically spo eigenvalues are not properly" << std::endl;
1114  std::cout << "included, so improper choice of orbitals may result." << std::endl;
1115  }
1116  const int int_kpts_sz = static_cast<int>(kpts.size());
1117  outfile_.write(int_kpts_sz, "number_of_kpoints");
1118  outfile_.write(nspin, "number_of_spins");
1119 
1120  double avgNup = 0.0;
1121  double avgNdn = 0.0;
1122  // go through kpt by kpt and write
1123  for (int i = 0; i < kpts.size(); i++)
1124  {
1125  stringstream kptElemName;
1126  kptElemName << "kpoint_" << i;
1127  outfile_.push(kptElemName.str());
1128 
1129  vector<double> kvector;
1130  kvector.push_back(kpts[i].kx);
1131  kvector.push_back(kpts[i].ky);
1132  kvector.push_back(kpts[i].kz);
1133  //writeNumsToHDF("numsym", 1, kpt_group);
1134  //writeNumsToHDF("symgroup", 1, kpt_group);
1135  outfile_.write(kvector, "reduced_k");
1136  const double dbl_weight = 1.0 / static_cast<double>(kpts.size());
1137  outfile_.write(dbl_weight, "weight");
1138 
1139  if (i == 0)
1140  {
1141  // figure out the order of the g-vectors
1142  // write them to an integer array and then put it in the element
1143  vector<int> gvectors;
1144  for (int ix = 0; ix < nx; ix++)
1145  {
1146  for (int iy = 0; iy < ny; iy++)
1147  {
1148  for (int iz = 0; iz < nz; iz++)
1149  {
1150  gvectors.push_back(wrapped(ix, nx));
1151  gvectors.push_back(wrapped(iy, ny));
1152  gvectors.push_back(wrapped(iz, nz));
1153  }
1154  }
1155  }
1156 
1157  array<int, 2> dims{nx * ny * nz, 3};
1158  outfile_.writeSlabReshaped(gvectors, dims, "gvectors");
1159  const int int_tot_num = nx * ny * nz;
1160  outfile_.write(int_tot_num, "number_of_gvectors");
1161  }
1162 
1163 
1164  // here is where we will read in both the occupations for the
1165  // kpoint (species depenent if needed)
1166  // and also the wavefunction (in real space)
1167  // fourier transform it and write it into the appropriate hdf element
1168  double nup = 0;
1169  double ndn = 0;
1170 
1171  outfile_.push("spin_0");
1172  const XmlNode* upnd = kptToUpNode[kpts[i]];
1173  handleSpinGroup(upnd, nup, fftCont);
1174  outfile_.pop();
1175 
1176  if (nspin == 2)
1177  {
1178  outfile_.push("spin_1");
1179  const XmlNode* dnnd = kptToDnNode[kpts[i]];
1180  handleSpinGroup(dnnd, ndn, fftCont);
1181  outfile_.pop();
1182  }
1183  else
1184  {
1185  ndn = nup;
1186  }
1187 
1188  avgNup += nup / static_cast<double>(kpts.size());
1189  avgNdn += ndn / static_cast<double>(kpts.size());
1190  }
1191  outfile_.pop();
1192  vector<int> nels;
1193  nels.push_back(static_cast<int>(std::floor(avgNup + 0.1)));
1194  nels.push_back(static_cast<int>(std::floor(avgNdn + 0.1)));
1195  outfile_.write(nels, "number_of_electrons");
1196  outfile_.pop();
1197 }
int getNx() const
Definition: FftContainer.h:34
void writeVersion()
Definition: WriteEshdf.cpp:218
double getOccupation(const XmlNode *nd) const
Definition: WriteEshdf.cpp:96
bool open(const std::filesystem::path &fname, unsigned flags=H5F_ACC_RDWR)
open a file
bool operator==(const KPoint &kp) const
Definition: WriteEshdf.cpp:52
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
Tensor< T, D >::Type_t det(const Tensor< T, D > &a)
Definition: TensorOps.h:838
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
void writeFormat()
Definition: WriteEshdf.cpp:234
Definition: XmlRep.h:81
void processKPts(const XmlNode &band_structure_xml, const std::vector< double > &ptvs, std::vector< std::vector< double >> &eigenvals, std::vector< std::vector< double >> &occupations, std::vector< KPoint > &kpts, std::vector< double > &weights, std::vector< int > &ngvecs)
Definition: WriteEshdf.cpp:568
void handleDensity(const XmlNode &qeXml, const std::string &dir_name, int spinpol)
Definition: WriteEshdf.cpp:492
void close()
close all the open groups and file
Definition: hdf_archive.cpp:38
std::vector< double > getPtvs(const XmlNode &qeXml)
Definition: WriteEshdf.cpp:660
int getIntsOnly(const std::string &str) const
Definition: WriteEshdf.cpp:261
class to handle hdf file
Definition: hdf_archive.h:51
void readKptGvecs(int kpt_num, const std::string &dir_name, int spinpol, momap_t &morefmap)
Definition: WriteEshdf.cpp:684
void readSlabReshaped(T &data, const std::array< IT, RANK > &shape, const std::string &aname)
read file dataset with a specific shape into a container and check status
Definition: hdf_archive.h:321
qmcplusplus::hdf_archive openHdfFileForRead(const std::string &fname)
Definition: WriteEshdf.cpp:477
std::string getName() const
Definition: XmlRep.h:114
void writeCreator()
Definition: WriteEshdf.cpp:224
void readSlabSelection(T &data, const std::array< IT, RANK > &readSpec, const std::string &aname)
read a portion of the data from the group aname and check status runtime error is issued on I/O error...
Definition: hdf_archive.h:345
bool getShape(const std::string &aname, std::vector< int > &sizes_out)
read the shape of multidimensional filespace from the group aname this function can be used to query ...
Definition: hdf_archive.h:231
void fixKsNorm(double factor)
Definition: FftContainer.h:51
bool operator<(const KPoint &kp) const
Definition: WriteEshdf.cpp:60
void getValue(T &result) const
Definition: XmlRep.h:206
void handleSpinGroup(const XmlNode *nd, double &nocc, FftContainer &cont)
Definition: WriteEshdf.cpp:110
std::map< std::vector< int >, std::complex< double > > momap_t
Definition: WriteEshdf.h:34
void writeQEElectrons(const XmlNode &qeXml, const std::string &dir_name)
Definition: WriteEshdf.cpp:980
void writeQEAtoms(const XmlNode &qeXml)
Definition: WriteEshdf.cpp:352
void readInEigFcn(const XmlNode &nd, FftContainer &cont)
Definition: WriteEshdf.cpp:152
KPoint(double x, double y, double z)
Definition: WriteEshdf.cpp:33
void handleKpt(int kpt_num, const std::string &dir_name, KPoint &kpt, const std::vector< double > &eigenvalues, double weight, int spinpol, int noncol, const momap_t &moref)
Definition: WriteEshdf.cpp:713
KPoint & operator=(const KPoint &kp)
Definition: WriteEshdf.cpp:45
KPoint(const KPoint &kp)
Definition: WriteEshdf.cpp:39
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
void writeQboxBoilerPlate(const XmlNode &qboxSample)
Definition: WriteEshdf.cpp:240
int getQboxIndex(int x, int y, int z) const
Definition: FftContainer.h:39
double kx
Definition: WriteEshdf.cpp:24
void getNumElectrons(std::vector< std::vector< double >> &occupations, std::vector< double > &weights, int &nup, int &ndn, int spinpol, int ncol)
Definition: WriteEshdf.cpp:608
int getNy() const
Definition: FftContainer.h:35
fftw_complex * kspace
Definition: FftContainer.h:25
void writeQEBoilerPlate(const XmlNode &qeXml)
Definition: WriteEshdf.cpp:279
void read(T &data, const std::string &aname)
read the data from the group aname and check status runtime error is issued on I/O error ...
Definition: hdf_archive.h:306
EshdfFile(const EshdfFile &f)
XmlNode & getChild(const std::string &name)
Definition: XmlRep.cpp:458
std::vector< int > dims
void writeApplication(const std::string &appName, int major, int minor, int sub)
Definition: WriteEshdf.cpp:206
int wrapped(int i, int size) const
Definition: WriteEshdf.cpp:84
std::pair< std::vector< int >, std::complex< double > > mopair_t
Definition: WriteEshdf.h:35
int getNumChildren() const
Definition: XmlRep.h:150
void writeQboxElectrons(const XmlNode &qboxSample)
int getAttributeIndex(const std::string &name, int strict=0) const
Definition: XmlRep.cpp:482
void executeFFT()
Definition: FftContainer.h:83
double ky
Definition: WriteEshdf.cpp:25
void writeQboxAtoms(const XmlNode &qboxSample)
Definition: WriteEshdf.cpp:412
void getAttribute(const std::string &name, T &result) const
Definition: XmlRep.h:191
const char version[]
Definition: HDFVersion.h:30
void writeQESupercell(const XmlNode &qeXml)
Definition: WriteEshdf.cpp:327
int getNz() const
Definition: FftContainer.h:36
double kz
Definition: WriteEshdf.cpp:26
void writeQboxSupercell(const XmlNode &qboxSample)
Definition: WriteEshdf.cpp:304
fftw_complex * rspace
Definition: FftContainer.h:24
MakeReturn< UnaryNode< FnFloor, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t floor(const Vector< T1, C1 > &l)