QMCPACK
DiracParser.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) 2021 QMCPACK developers.
6 //
7 // File developed by: Cody A. Melton, cmelton@sandia.gov, Sandia National Laboratories
8 //
9 // File created by: Cody A. Melton, cmelton@sandia.gov, Sandia National Laboratories
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #include "QMCTools/DiracParser.h"
13 #include "io/hdf/hdf_archive.h"
14 #include <cstdio>
15 #include <algorithm>
16 
17 using primExpCoeff = std::pair<double, double>;
18 using basisFunc = std::vector<primExpCoeff>;
19 
20 fermIrrep::fermIrrep(std::string label_in, int nSpinors, int numAO) : label(label_in)
21 {
22  energies.resize(nSpinors, 0);
23  orbtypes.resize(nSpinors, OrbType::VIRTUAL);
24  spinor_mo_coeffs.resize(nSpinors);
25  for (int mo = 0; mo < nSpinors; mo++)
26  {
27  spinor_mo_coeffs[mo].resize(numAO);
28  for (int ao = 0; ao < numAO; ao++)
29  spinor_mo_coeffs[mo][ao].resize(4, 0);
30  }
31 }
32 
34 {
35  std::string new_label = label;
36  assert(label[1] == '1');
37  new_label[1] = '2';
38  int nspinor = get_num_spinors();
39  int numAO = get_num_ao();
40  fermIrrep kp(new_label, nspinor, numAO);
41  kp.energies = energies;
42  for (int mo = 0; mo < nspinor; mo++)
43  {
44  for (int ao = 0; ao < numAO; ao++)
45  {
46  kp.spinor_mo_coeffs[mo][ao][0] = -spinor_mo_coeffs[mo][ao][2];
47  kp.spinor_mo_coeffs[mo][ao][1] = spinor_mo_coeffs[mo][ao][3];
48  kp.spinor_mo_coeffs[mo][ao][2] = spinor_mo_coeffs[mo][ao][0];
49  kp.spinor_mo_coeffs[mo][ao][3] = -spinor_mo_coeffs[mo][ao][1];
50  }
51  }
52  return kp;
53 }
54 
55 cosciRep::cosciRep(std::string in_label, int nstates) : label(in_label) { states.resize(nstates); }
56 
57 void cosciRep::printInfo(std::ostream& os, int& tot_state_count)
58 {
59  os << " Representation: " << label << " with " << states.size() << " states" << std::endl;
60  os << "state# Energies and Ndets: " << std::endl;
61  for (int i = 0; i < states.size(); i++)
62  {
63  os << " " << tot_state_count << " " << states[i].energy << " " << states[i].coeffs.size() << std::endl;
64  tot_state_count++;
65  }
66 }
67 
68 DiracParser::DiracParser(int argc, char** argv) : QMCGaussianParserBase(argc, argv)
69 {
70  ECP = false;
71  BohrUnit = true;
72  PBC = false;
73  isSpinor = true;
74  angular_type = "cartesian";
75  expandYlm = "Dirac";
76  normMap = {
77  {"s", 1.0},
78  {"px", 1.0},
79  {"py", 1.0},
80  {"pz", 1.0},
81  {"dxx", std::sqrt(3)},
82  {"dyy", std::sqrt(3)},
83  {"dzz", std::sqrt(3)},
84  {"dxy", 1.0},
85  {"dxz", 1.0},
86  {"dyz", 1.0},
87  {"fxxx", std::sqrt(15)},
88  {"fyyy", std::sqrt(15)},
89  {"fzzz", std::sqrt(15)},
90  {"fxxy", std::sqrt(3)},
91  {"fxxz", std::sqrt(3)},
92  {"fxyy", std::sqrt(3)},
93  {"fyyz", std::sqrt(3)},
94  {"fxzz", std::sqrt(3)},
95  {"fyzz", std::sqrt(3)},
96  {"fxyz", 1},
97  {"g400", std::sqrt(105)},
98  {"g040", std::sqrt(105)},
99  {"g004", std::sqrt(105)},
100  {"g310", std::sqrt(15)},
101  {"g301", std::sqrt(15)},
102  {"g130", std::sqrt(15)},
103  {"g031", std::sqrt(15)},
104  {"g103", std::sqrt(15)},
105  {"g013", std::sqrt(15)},
106  {"g220", std::sqrt(9)},
107  {"g202", std::sqrt(9)},
108  {"g022", std::sqrt(9)},
109  {"g211", std::sqrt(3)},
110  {"g121", std::sqrt(3)},
111  {"g112", std::sqrt(3)},
112  {"h500", std::sqrt(945)},
113  {"h050", std::sqrt(945)},
114  {"h005", std::sqrt(945)},
115  {"h410", std::sqrt(105)},
116  {"h401", std::sqrt(105)},
117  {"h140", std::sqrt(105)},
118  {"h041", std::sqrt(105)},
119  {"h104", std::sqrt(105)},
120  {"h014", std::sqrt(105)},
121  {"h320", std::sqrt(45)},
122  {"h302", std::sqrt(45)},
123  {"h230", std::sqrt(45)},
124  {"h032", std::sqrt(45)},
125  {"h203", std::sqrt(45)},
126  {"h023", std::sqrt(45)},
127  {"h311", std::sqrt(15)},
128  {"h131", std::sqrt(15)},
129  {"h113", std::sqrt(15)},
130  {"h221", std::sqrt(9)},
131  {"h212", std::sqrt(9)},
132  {"h122", std::sqrt(9)},
133  {"i600", std::sqrt(10395)},
134  {"i060", std::sqrt(10395)},
135  {"i006", std::sqrt(10395)},
136  {"i510", std::sqrt(945)},
137  {"i501", std::sqrt(945)},
138  {"i150", std::sqrt(945)},
139  {"i051", std::sqrt(945)},
140  {"i105", std::sqrt(945)},
141  {"i015", std::sqrt(945)},
142  {"i420", std::sqrt(315)},
143  {"i402", std::sqrt(315)},
144  {"i240", std::sqrt(315)},
145  {"i042", std::sqrt(315)},
146  {"i204", std::sqrt(315)},
147  {"i024", std::sqrt(315)},
148  {"i411", std::sqrt(105)},
149  {"i141", std::sqrt(105)},
150  {"i114", std::sqrt(105)},
151  {"i330", std::sqrt(225)},
152  {"i303", std::sqrt(225)},
153  {"i033", std::sqrt(225)},
154  {"i321", std::sqrt(45)},
155  {"i312", std::sqrt(45)},
156  {"i231", std::sqrt(45)},
157  {"i132", std::sqrt(45)},
158  {"i213", std::sqrt(45)},
159  {"i123", std::sqrt(45)},
160  {"i222", std::sqrt(27)},
161  };
162 }
163 
164 void DiracParser::parse(const std::string& fname)
165 {
166  std::string dirac_out = fname;
167  std::ifstream fin(dirac_out.c_str());
168  if (fin.fail())
169  {
170  std::cerr << "Error when opening file: " << dirac_out << std::endl;
171  abort();
172  }
173  pivot_begin = fin.tellg();
174 
175  search(fin, "Release DIRAC", aline);
176  parsewords(aline.c_str(), currentWords);
177  version = std::stoi(currentWords[2].erase(0, 5));
178 
179  search(fin, "Number of atom types", aline);
180  parsewords(aline.c_str(), currentWords);
181  NumberOfSpecies = std::atoi(currentWords.back().c_str());
182 
183  search(fin, "Total number of atoms", aline);
184  parsewords(aline.c_str(), currentWords);
185  NumberOfAtoms = std::atoi(currentWords.back().c_str());
186 
187  std::cout << "Found " << NumberOfSpecies << " unique species" << std::endl;
188  std::cout << "Found " << NumberOfAtoms << " total number of atoms" << std::endl;
189 
190  search(fin, "*SCF: Set-up for");
191  skiplines(fin, 2);
192  getwords(currentWords, fin);
193  if (currentWords[1] == "Closed")
194  {
195  NumberOfBeta = 0;
196  NumberOfAlpha = std::stoi(currentWords[6]);
198  }
199  else if (currentWords[1] == "Open")
200  {
201  NumberOfBeta = 0;
202  search(fin, "* Shell specifications:");
203  lookFor(fin, "Total", aline);
204  parsewords(aline.c_str(), currentWords);
205  NumberOfAlpha = std::stoi(currentWords[1]);
207  }
208  else
209  {
210  std::cerr << "Error number of electrons" << std::endl;
211  abort();
212  }
213 
215  GroupName.resize(NumberOfAtoms);
216  getGeometry(fin);
217  getGaussianCenters(fin);
218  getSpinors(fin);
219  getWF(fin);
220  std::cout << std::endl;
221  std::cout << std::endl;
222  std::cout << std::endl;
223 }
224 
225 void DiracParser::getGeometry(std::istream& is)
226 {
227  const double ang_to_bohr = 1.0 / 0.529177e0;
228  is.clear();
229  is.seekg(pivot_begin);
230 
231  search(is, "label atoms charge prim cont basis", aline);
232  skiplines(is, 1);
233  std::map<std::string, int> zMap;
234  std::map<std::string, int> zeffMap;
235  for (int uat = 0; uat < NumberOfSpecies; uat++)
236  {
237  getwords(currentWords, is);
238  std::string name = currentWords[0];
239  int zeff = std::stoi(currentWords[2]);
240  for (int i = 0; i < IonName.size(); i++)
241  {
242  if (IonName[i] == name)
243  {
244  std::pair<std::string, int> x(name, i);
245  std::pair<std::string, int> y(name, zeff);
246  zMap.insert(x);
247  zeffMap.insert(y);
248  break;
249  }
250  }
251  skiplines(is, 1);
252  }
253  search(is, "total: ", aline);
254  parsewords(aline.c_str(), currentWords);
255  SizeOfBasisSet = std::stoi(currentWords[4]);
256 
257  //now overwrite charge for pseudsized atoms
258  is.clear();
259  is.seekg(pivot_begin);
260  while (lookFor(is, "Nuclear Gaussian exponent for atom", aline))
261  {
262  parsewords(aline.c_str(), currentWords);
263  int z = std::stoi(currentWords[7]);
264  std::getline(is, aline);
265  if (aline.size() == 0)
266  break;
267  //found an ECP to replace
268  ECP = true;
269  getwords(currentWords, is);
270  int zeff = std::stoi(currentWords[6]);
271  zeffMap.find(IonName[z])->second = zeff;
272  }
273  is.clear();
274  is.seekg(pivot_begin);
275 
276  search(is, "Cartesian coordinates in XYZ format", aline);
277  skiplines(is, 4);
278  SpeciesSet& species(IonSystem.getSpeciesSet());
279  for (int iat = 0; iat < NumberOfAtoms; iat++)
280  {
281  getwords(currentWords, is);
282  for (int d = 0; d < 3; d++)
283  {
284  IonSystem.R[iat][d] = std::stod(currentWords[1 + d]) * ang_to_bohr;
285  }
286  GroupName[iat] = currentWords[0];
287  int speciesID = species.addSpecies(GroupName[iat]);
288  IonSystem.GroupID[iat] = speciesID;
289  species(AtomicNumberIndex, speciesID) = zMap.find(GroupName[iat])->second;
290  species(IonChargeIndex, speciesID) = zeffMap.find(GroupName[iat])->second;
291  }
292 }
293 
294 void DiracParser::getGaussianCenters(std::istream& is)
295 {
296  is.clear();
297  is.seekg(pivot_begin);
298 
299  search(is, "Contents of the molecule file", aline);
300  skiplines(is, 5);
301  getwords(currentWords, is);
302  int nat = std::stoi(currentWords[1]);
303  assert(nat == NumberOfSpecies);
304  basisset.resize(NumberOfSpecies);
305  SpeciesSet& species(IonSystem.getSpeciesSet());
306  for (int iat = 0; iat < NumberOfSpecies; iat++)
307  {
308  basisset[iat].elementType = species.speciesName[iat];
309  std::vector<int> numPerL;
310  search(is, "LARGE", aline);
311  parsewords(aline.c_str(), currentWords);
312  if (currentWords[1] != "EXPLICIT")
313  {
314  std::cerr << "Cannot extract basis. Rerun with EXPLICIT basis" << std::endl;
315  abort();
316  }
317  for (int n = 3; n < currentWords.size(); n++)
318  {
319  numPerL.push_back(std::stoi(currentWords[n]));
320  }
321  //loop through each angular momentum
322  for (int l = 0; l < numPerL.size(); l++)
323  {
324  for (int il = 0; il < numPerL[l]; il++)
325  {
326  search(is, "f ", aline);
327  parsewords(aline.c_str(), currentWords);
328  int nprim = std::stoi(currentWords[1]);
329  int ncont = std::stoi(currentWords[2]);
330  //each basis in this current block is uncontracted
331  if (ncont == 0)
332  {
333  for (int n = 0; n < nprim; n++)
334  {
335  getwords(currentWords, is);
336  primBasis p;
337  p.first = std::stod(currentWords[0]);
338  p.second = 1.0;
339  basisGroup bas;
340  bas.n = basisset[iat].basisGroups.size();
341  bas.l = l;
342  bas.radfuncs.push_back(p);
343  basisset[iat].basisGroups.push_back(bas);
344  }
345  }
346  else
347  {
348  int bgstart = basisset[iat].basisGroups.size();
349  for (int n = 0; n < ncont; n++)
350  {
351  basisGroup bg;
352  bg.n = basisset[iat].basisGroups.size();
353  bg.l = l;
354  basisset[iat].basisGroups.push_back(bg);
355  }
356  for (int n = 0; n < nprim; n++)
357  {
358  getwords(currentWords, is);
359  assert(currentWords.size() == ncont + 1);
360  for (int c = 0; c < ncont; c++)
361  {
362  primBasis p;
363  p.first = std::stod(currentWords[0]);
364  p.second = std::stod(currentWords[c + 1]);
365  basisset[iat].basisGroups[bgstart + c].radfuncs.push_back(p);
366  }
367  }
368  }
369  }
370  }
371  }
372 
373  //Store data to QMCGaussian output format
374  std::map<std::string, int> basisDataMap;
375  int nUniqAt = 0;
376  for (int i = 0; i < NumberOfAtoms; i++)
377  {
378  std::map<std::string, int>::iterator it(basisDataMap.find(GroupName[i]));
379  if (it == basisDataMap.end())
380  {
381  basisDataMap[GroupName[i]] = nUniqAt++;
382  }
383  }
384  gBound.resize(NumberOfAtoms + 1);
385  gShell.clear();
386  gNumber.clear();
387  gExp.clear();
388  gC0.clear();
389  gC1.clear();
390  int gtot = 0;
391  for (int i = 0; i < NumberOfAtoms; i++)
392  {
393  std::map<std::string, int>::iterator it(basisDataMap.find(GroupName[i]));
394  if (it == basisDataMap.end())
395  {
396  std::cerr << "Error in parser.\n";
397  abort();
398  }
399  gBound[i] = gtot;
400  int indx = it->second;
401  gtot += basisset[indx].basisGroups.size();
402  for (int k = 0; k < basisset[indx].basisGroups.size(); k++)
403  {
404  int l = basisset[indx].basisGroups[k].l;
405  int sh = (l == 0) ? 1 : l + 2;
406  gShell.push_back(sh);
407  }
408  for (int k = 0; k < basisset[indx].basisGroups.size(); k++)
409  gNumber.push_back(basisset[indx].basisGroups[k].radfuncs.size());
410  for (int k = 0; k < basisset[indx].basisGroups.size(); k++)
411  {
412  for (int c = 0; c < basisset[indx].basisGroups[k].radfuncs.size(); c++)
413  {
414  gExp.push_back(basisset[indx].basisGroups[k].radfuncs[c].first);
415  gC0.push_back(basisset[indx].basisGroups[k].radfuncs[c].second);
416  }
417  }
418  }
419  gBound[NumberOfAtoms] = gtot;
420 }
421 
422 void DiracParser::getSpinors(std::istream& is)
423 {
424  std::cout << std::endl;
425  std::cout << "Reading spinor info" << std::endl;
426  std::cout << "========================================================================" << std::endl;
427  is.clear();
428  is.seekg(pivot_begin);
429 
430  search(is, "Output from DBLGRP");
431  skiplines(is, 2);
432  getwords(currentWords, is);
433  //look for "* Nirrep fermion irreps: irrep1 irrep2 ..."
434  int nirrep = currentWords.size() - 4;
435  std::vector<std::string> labels(nirrep);
436  for (int i = 0; i < nirrep; i++)
437  labels[i] = currentWords[4 + i];
438 
439  for (int i = 0; i < nirrep; i++)
440  {
441  is.clear();
442  is.seekg(pivot_begin);
443  search(is, "VECINP: Vector print");
444  std::string irstr = "- Orbitals in fermion ircop " + labels[i];
445  lookFor(is, irstr, aline);
446  parsewords(aline.c_str(), currentWords);
447  if (currentWords.back() == ":1..oo")
448  {
449  search(is, "* Occupation of subblocks");
450  lookFor(is, labels[i], aline);
451  lookFor(is, "tot.num. of pos.erg shells:", aline);
452  parsewords(aline.c_str(), currentWords);
453  int nj = currentWords.size() - 4;
454  int nspinors = 0;
455  for (int j = 0; j < nj; j++)
456  nspinors += std::stoi(currentWords[4 + j]);
457  irreps.push_back(fermIrrep(labels[i], nspinors, SizeOfBasisSet));
458  }
459  else
460  {
461  std::string splitby = ":.";
462  aline = currentWords.back();
463  parsewords(aline.c_str(), currentWords, splitby);
464  if (currentWords[0] != "1")
465  {
466  std::cerr << "Error: For vector printing, need to use 1..oo or 1..N" << std::endl;
467  abort();
468  }
469  int nspinors = std::stoi(currentWords[1]);
470  irreps.push_back(fermIrrep(labels[i], nspinors, SizeOfBasisSet));
471  }
472  }
473 
474  std::cout << "Found " << nirrep << " fermion irreps." << std::endl;
475  for (int i = 0; i < nirrep; i++)
476  std::cout << " irrep " << irreps[i].get_label() << " with " << irreps[i].get_num_spinors() << " spinors and "
477  << irreps[i].get_num_ao() << " AO coefficients." << std::endl;
478 
479  search(is, "Coefficients from DFCOEF", aline);
480  std::streampos startspinors = is.tellg();
481 
482  for (int i = 0; i < nirrep; i++)
483  {
484  is.clear();
485  is.seekg(startspinors);
486  std::string start_irrep = "Fermion ircop " + irreps[i].get_label();
487  search(is, start_irrep);
488  for (int mo = 0; mo < irreps[i].get_num_spinors(); mo++)
489  {
490  lookFor(is, "Electronic eigenvalue no.", aline);
491  parsewords(aline.c_str(), currentWords);
492  irreps[i].energies[mo] = std::stod(currentWords.back());
493  skiplines(is, 1);
494  while (std::getline(is, aline))
495  {
496  if (aline.size() == 0)
497  break;
498  if (std::string(aline).find("*********") != std::string::npos)
499  {
500  std::cerr << "ERROR parsing line: " << std::endl;
501  std::cerr << aline << std::endl;
502  std::cerr << "One of the printed AO coefficients is outside the default DIRAC print format" << std::endl;
503  std::cerr << "In order to continue, please change the following in DIRAC/src/dirac/dirout.F (around line 427)"
504  << std::endl;
505  std::cerr << " 100 FORMAT(3X,I5,2X,A12,2X,4F14.10)" << std::endl;
506  std::cerr << " to " << std::endl;
507  std::cerr << " 100 FORMAT(3X,I5,2X,A12,2X,4F20.10)" << std::endl;
508  std::cerr
509  << " and recompile DIRAC. Then rerun your particular calulcation in order to get accurate AO coefficients"
510  << std::endl;
511  abort();
512  }
513  parsewords(aline.c_str(), currentWords);
514  if (currentWords.size() != 9)
515  {
516  std::cerr << "ERROR parsing line: " << std::endl;
517  std::cerr << aline << std::endl;
518  std::cerr << "Expected line to be parsed into vector<string> of length 9" << std::endl;
519  std::cerr
520  << "Either recompile DIRAC in DIRAC/src/dirac/dirout.F (around line 427) to avoid this issue from now on"
521  << std::endl;
522  std::cerr << " 100 FORMAT(3X,I5,2X,A12,2X,4F14.10)" << std::endl;
523  std::cerr << " to " << std::endl;
524  std::cerr << " 100 FORMAT(3X,I5,2X,A12,2X,4F20.10)" << std::endl;
525  std::cerr << " or just add a space appropriately to this line" << std::endl;
526  abort();
527  }
528  int bidx = std::stoi(currentWords[0]) - 1;
529 
530  double norm = 1.0;
531  std::string label = currentWords[4];
532  normMapType::iterator it = normMap.find(label);
533  if (it != normMap.end())
534  norm = it->second;
535  else
536  {
537  std::cerr << "Unknown basis function type. Aborting" << std::endl;
538  abort();
539  }
540 
541  double up_r = std::stod(currentWords[5]);
542  double up_i = std::stod(currentWords[6]);
543  double dn_r = std::stod(currentWords[7]);
544  double dn_i = std::stod(currentWords[8]);
545 
546  irreps[i].spinor_mo_coeffs[mo][bidx][0] = up_r * norm;
547  irreps[i].spinor_mo_coeffs[mo][bidx][1] = up_i * norm;
548  irreps[i].spinor_mo_coeffs[mo][bidx][2] = dn_r * norm;
549  irreps[i].spinor_mo_coeffs[mo][bidx][3] = dn_i * norm;
550  }
551  }
552 
553  std::cout << "Found coefficients for " << irreps[i].get_label() << std::endl;
554  kp_irreps.push_back(irreps[i].generate_kramers_pair());
555  std::cout << "Generated kramers pair with irrep " << kp_irreps[i].get_label() << std::endl;
556  }
557 
558  std::cout << "Now we have the following spinors" << std::endl;
559  for (int i = 0; i < irreps.size(); i++)
560  {
561  std::cout << " irrep " << irreps[i].get_label() << " with " << irreps[i].get_num_spinors() << " spinors and "
562  << irreps[i].get_num_ao() << " AO coefficients." << std::endl;
563  std::cout << " irrep " << kp_irreps[i].get_label() << " with " << kp_irreps[i].get_num_spinors() << " spinors and "
564  << kp_irreps[i].get_num_ao() << " AO coefficients." << std::endl;
565  }
566 
567  numMO = 0;
568  for (int i = 0; i < irreps.size(); i++)
569  numMO += 2 * irreps[i].get_num_spinors(); //irrep and kp
570 }
571 
572 void DiracParser::getWF(std::istream& is)
573 {
574  is.clear();
575  is.seekg(pivot_begin);
576  std::cout << std::endl;
577  std::cout << "Parsing wave function info" << std::endl;
578  std::cout << "========================================================================" << std::endl;
579 
580  if (lookFor(is, "Resolution of open-shell states", aline))
581  {
582  bool closed = lookFor(is, "No open-shell electrons", aline);
583  if (closed)
584  {
585  std::cout << "Found single determinant wave function" << std::endl;
586  getSingleDet(is);
587  }
588  else
589  {
590  std::cout << "Found Complete Open-Shell CI (COSCI) wave function" << std::endl;
591  getCOSCI(is);
592  }
593  }
594  else
595  {
596  std::cout << "Found single determinant wave function" << std::endl;
597  getSingleDet(is);
598  }
599 }
600 
601 void DiracParser::getSingleDet(std::istream& is)
602 {
603  //energy order spinors across fermion irreps
604  std::cout << "Sorting spinors by energy" << std::endl;
605  std::vector<std::pair<double, std::pair<int, int>>> idx;
606  for (int ir = 0; ir < irreps.size(); ir++)
607  {
608  for (int mo = 0; mo < irreps[ir].get_num_spinors(); mo++)
609  {
610  std::pair<int, int> irmo(ir, mo);
611  std::pair<double, std::pair<int, int>> enirmo(irreps[ir].energies[mo], irmo);
612  idx.push_back(enirmo);
613  }
614  }
615  std::sort(idx.begin(), idx.end());
616 
617  //store in QMCGaussian data format
618  //storing in EigVec by up_real, dn_real, up_imag, dn_imag
619  //only sort energy for irrep, since kramers pairs kp_irreps are degenerate
620  EigVec.clear();
621  EigVal_alpha.clear();
622  EigVal_beta.clear();
623  std::vector<int> spinor_component = {0, 2, 1, 3};
624  for (int d = 0; d < 4; d++)
625  {
626  for (int i = 0; i < idx.size(); i++)
627  {
628  if (d == 0)
629  {
630  //store it twice, first spinor and its kramers pair
631  EigVal_alpha.push_back(idx[i].first);
632  EigVal_alpha.push_back(idx[i].first);
633  }
634  int ir = idx[i].second.first;
635  int mo = idx[i].second.second;
636  for (int ao = 0; ao < irreps[ir].get_num_ao(); ao++)
637  EigVec.push_back(irreps[ir].spinor_mo_coeffs[mo][ao][spinor_component[d]]);
638  for (int ao = 0; ao < irreps[ir].get_num_ao(); ao++)
639  EigVec.push_back(kp_irreps[ir].spinor_mo_coeffs[mo][ao][spinor_component[d]]);
640  }
641  }
642 }
643 
644 void DiracParser::parseCOSCIOrbInfo(std::istream& is, const int irrep_idx, OrbType type)
645 {
646  std::string orbtype_str;
647  if (type == OrbType::CORE)
648  orbtype_str = "Core";
649  else if (type == OrbType::ACTIVE)
650  orbtype_str = "Active";
651  else
652  {
653  std::cerr << "Orb type must be CORE or ACTIVE" << std::endl;
654  abort();
655  }
656 
657  is.seekg(pivot_begin);
658  search(is, "Resolution of open-shell states");
659  std::string tmp = "- " + orbtype_str + " orbitals";
660  search(is, tmp);
661  lookFor(is, irreps[irrep_idx].label, aline);
662  parsewords(aline.c_str(), currentWords);
663  assert(currentWords.back() == irreps[irrep_idx].label);
664  skiplines(is, 1);
665  getwords(currentWords, is);
666  if (currentWords[0] == "Index")
667  {
668  int norb = std::stoi(currentWords[2]);
669  int count = 0;
670  while (count < norb)
671  {
672  getline(is, aline);
673  if (aline.size() == 0)
674  continue;
675  parsewords(aline.c_str(), currentWords);
676  for (int i = 0; i < currentWords.size(); i++, count++)
677  {
678  int idx = std::stoi(currentWords[i]) - 1;
679  irreps[irrep_idx].orbtypes[idx] = type;
680  kp_irreps[irrep_idx].orbtypes[idx] = type;
681  }
682  if (count > norb)
683  {
684  std::cerr << "Error: Read in more indices than exist for irrep " << irreps[irrep_idx].label << std::endl;
685  abort();
686  }
687  else if (count == norb)
688  break;
689  }
690  }
691 }
692 
693 int DiracParser::sortAndStoreCOSCIOrbs(OrbType type, const int spinor_component)
694 {
695  int total = 0;
696  for (int ir = 0; ir < irreps.size(); ir++)
697  {
698  std::vector<std::pair<double, std::pair<int, int>>> idx;
699  for (int mo = 0; mo < irreps[ir].get_num_spinors(); mo++)
700  {
701  if (irreps[ir].orbtypes[mo] == type)
702  {
703  std::pair<int, int> irmo(ir, mo);
704  std::pair<double, std::pair<int, int>> enirmo(irreps[ir].energies[mo], irmo);
705  idx.push_back(enirmo);
706  }
707  }
708 
709  for (int i = 0; i < idx.size(); i++)
710  {
711  if (spinor_component == 0)
712  {
713  EigVal_alpha.push_back(idx[i].first);
714  total++;
715  }
716  int ir = idx[i].second.first;
717  int mo = idx[i].second.second;
718  for (int ao = 0; ao < irreps[ir].get_num_ao(); ao++)
719  EigVec.push_back(irreps[ir].spinor_mo_coeffs[mo][ao][spinor_component]);
720  }
721  //now store KP for this irrep
722  for (int i = 0; i < idx.size(); i++)
723  {
724  if (spinor_component == 0)
725  {
726  EigVal_alpha.push_back(idx[i].first);
727  total++;
728  }
729  int ir = idx[i].second.first;
730  int mo = idx[i].second.second;
731  for (int ao = 0; ao < irreps[ir].get_num_ao(); ao++)
732  EigVec.push_back(kp_irreps[ir].spinor_mo_coeffs[mo][ao][spinor_component]);
733  }
734  }
735 
736  return total;
737 }
738 
739 void DiracParser::getCOSCI(std::istream& is)
740 {
741  is.clear();
742  multideterminant = true;
743 
744  //find closed info. Info is initialized as virtual.
745  //Just need to update core and active
746  for (int i = 0; i < irreps.size(); i++)
747  {
750  }
751 
752  std::cout << std::endl;
753  std::cout << "Orbital Info" << std::endl;
754  std::cout << "------------------------------------" << std::endl;
755  for (int i = 0; i < irreps.size(); i++)
756  {
757  std::cout << "irrep: " << irreps[i].label << std::endl;
758  int closed = 0;
759  int active = 0;
760  int virt = 0;
761  for (int j = 0; j < irreps[i].orbtypes.size(); j++)
762  {
763  if (irreps[i].orbtypes[j] == OrbType::CORE)
764  closed += 1;
765  else if (irreps[i].orbtypes[j] == OrbType::ACTIVE)
766  active += 1;
767  else if (irreps[i].orbtypes[j] == OrbType::VIRTUAL)
768  virt += 1;
769  }
770  std::cout << " closed : " << closed << std::endl;
771  std::cout << " active : " << active << std::endl;
772  std::cout << " virtual : " << virt << std::endl;
773  std::cout << " total : " << closed + active + virt << std::endl;
774  }
775 
776  std::cout << std::endl;
777  std::cout << "Sorting spinors into DIRAC COSCI order" << std::endl;
778 
779  //store in QMCGaussian data format
780  //storing in EigVec by up_real, dn_real, up_imag, dn_imag
781  EigVec.clear();
782  EigVal_alpha.clear();
783  EigVal_beta.clear();
784  //save real part of up component of spinor in EigVec first
785  int total_core = sortAndStoreCOSCIOrbs(OrbType::CORE, 0);
786  int total_active = sortAndStoreCOSCIOrbs(OrbType::ACTIVE, 0);
787  int total_virtual = sortAndStoreCOSCIOrbs(OrbType::VIRTUAL, 0);
788  //save real part of dn compeonent of spinor in Eigvec
792  //save imag part of up compeonent of spinor in Eigvec
796  //save imag part of dn compeonent of spinor in Eigvec
800 
801 
802  //set occstrs for core and virtual
803  std::string core_occstr;
804  for (int i = 0; i < total_core; i++)
805  core_occstr += "1";
806  std::string virt_occstr;
807  for (int i = 0; i < total_virtual; i++)
808  virt_occstr += "0";
809  //active occstr found from COSCI states below
810 
811  is.seekg(pivot_begin);
812  search(is, "Resolution of open-shell states");
813  search(is, "Orbital Representation");
814 
815  std::vector<std::streampos> rep_pos;
816  while (lookFor(is, "Representation", aline))
817  rep_pos.push_back(is.tellg());
818  is.clear();
819 
820  for (int i = 0; i < rep_pos.size(); i++)
821  {
822  is.seekg(rep_pos[i]);
823  lookFor(is, "Population analysis", aline);
824  parsewords(aline.c_str(), currentWords);
825  std::string label = currentWords.back();
826  getwords(currentWords, is);
827  int nstates = std::stoi(currentWords[2]);
828  cosciRep rep(label, nstates);
829  skiplines(is, 3);
830  for (int j = 0; j < nstates; j++)
831  {
832  std::vector<double> ci_coeffs;
833  std::vector<std::string> ci_occs;
834  double energy = 0.0;
835  while (getline(is, aline))
836  {
837  if (aline.size() == 0)
838  break;
839  parsewords(aline.c_str(), currentWords);
840  if (currentWords.size() == 1)
841  energy = std::stod(currentWords[0]);
842  if (currentWords[0] == "Sum")
843  {
844  getline(is, aline);
845  break;
846  }
847  if (currentWords.size() == 5 && currentWords[0] != "Sum")
848  {
849  ci_coeffs.push_back(std::stod(currentWords[3]));
850  std::string tmp = core_occstr + currentWords[1] + virt_occstr;
851  ci_occs.push_back(tmp);
852  }
853  }
854  //finished reading CI coeffs for state
855  ciState ci;
856  ci.energy = energy;
857  ci.occstrings = ci_occs;
858  ci.coeffs = ci_coeffs;
859  rep.states[j] = ci;
860  }
861  cosciReps.push_back(rep);
862  }
863 
864  std::cout << std::endl;
865  std::cout << "COSCI State Info" << std::endl;
866  std::cout << "------------------------------------" << std::endl;
867  std::cout << "Found " << cosciReps.size() << " representations" << std::endl;
868  int state_count = 0;
869  for (int i = 0; i < cosciReps.size(); i++)
870  cosciReps[i].printInfo(std::cout, state_count);
871  std::cout << "Saving wave function for target state " << target_state << std::endl;
872  std::cout << "note: if you want another state run with --TargetState #_of_desired_state shown above" << std::endl;
873 
874  //store info for desired state in QMCGausianParserBase structures
875  bool found = false;
876  state_count = 0;
877  for (int i = 0; i < cosciReps.size(); i++)
878  {
879  for (int j = 0; j < cosciReps[i].states.size(); j++)
880  {
881  if (state_count == target_state)
882  {
883  CIcoeff = cosciReps[i].states[j].coeffs;
884  CIalpha = cosciReps[i].states[j].occstrings;
885  CIbeta = CIalpha; //just store it. It isn't written to h5
886  found = true;
887  ci_nstates = CIalpha[0].size();
888  ci_size = CIcoeff.size();
889  ci_nca = 0;
891  }
892  state_count++;
893  }
894  }
895  if (!found)
896  {
897  std::cerr << "Could not find requested state" << std::endl;
898  abort();
899  }
900 }
std::vector< value_type > EigVal_beta
int NumberOfSpecies
Definition: DiracParser.h:88
std::vector< cosciRep > cosciReps
Definition: DiracParser.h:96
std::vector< std::string > currentWords
Definition: SimpleParser.h:49
void parse(const std::string &fname) override
std::string label
Definition: DiracParser.h:66
cosciRep(std::string in_label, int nstates)
Definition: DiracParser.cpp:55
std::vector< double > CIcoeff
std::vector< primExpCoeff > basisFunc
Definition: DiracParser.cpp:18
fermIrrep(std::string label_in, int nSpinors, int numAO)
Definition: DiracParser.cpp:20
std::vector< std::vector< std::vector< double > > > spinor_mo_coeffs
Definition: DiracParser.h:47
void getWF(std::istream &is)
std::vector< ciState > states
Definition: DiracParser.h:67
std::vector< std::string > GroupName
std::vector< std::string > occstrings
Definition: DiracParser.h:58
void skiplines(std::istream &is, int n)
Definition: SimpleParser.h:51
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
void getGeometry(std::istream &is)
std::vector< double > coeffs
Definition: DiracParser.h:59
std::vector< value_type > EigVal_alpha
OrbType
Definition: DiracParser.h:35
std::vector< value_type > gC0
double norm(const zVec &c)
Definition: VectorOps.h:118
unsigned parsewords(const char *inbuf, std::vector< std::string > &slist, const std::string &extra_tokens)
double energy
Definition: DiracParser.h:57
std::vector< primBasis > radfuncs
Definition: DiracParser.h:26
std::vector< value_type > EigVec
void getSingleDet(std::istream &is)
int search(std::istream &is, const std::string &keyword)
Definition: SimpleParser.h:89
ParticlePos R
Position.
Definition: ParticleSet.h:79
fermIrrep generate_kramers_pair()
Definition: DiracParser.cpp:33
std::vector< value_type > gExp
static std::map< int, std::string > IonName
std::vector< OrbType > orbtypes
Definition: DiracParser.h:46
int sortAndStoreCOSCIOrbs(OrbType type, const int spinor_component)
std::streampos pivot_begin
Definition: DiracParser.h:87
std::pair< double, double > primExpCoeff
Definition: DiracParser.cpp:17
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
std::vector< std::string > CIalpha
normMapType normMap
Definition: DiracParser.h:92
void create(const std::vector< int > &agroup)
create grouped particles
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
bool lookFor(std::istream &is, const std::string &keyword)
Definition: SimpleParser.h:130
std::vector< double > energies
Definition: DiracParser.h:45
void getSpinors(std::istream &is)
std::vector< int > gNumber
void getCOSCI(std::istream &is)
int get_num_ao()
Definition: DiracParser.h:51
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
DiracParser(int argc, char **argv)
Definition: DiracParser.cpp:68
int getwords(std::vector< std::string > &slist, std::istream &fp, std::string &aline)
std::vector< std::string > CIbeta
std::vector< value_type > gC1
void printInfo(std::ostream &os, int &tot_state_count)
Definition: DiracParser.cpp:57
std::pair< double, double > primBasis
Definition: DiracParser.h:20
void getGaussianCenters(std::istream &is)
std::vector< atBasisSet > basisset
Definition: DiracParser.h:91
std::string aline
Definition: DiracParser.h:90
std::vector< fermIrrep > kp_irreps
Definition: DiracParser.h:95
int get_num_spinors()
Definition: DiracParser.h:50
void parseCOSCIOrbInfo(std::istream &is, const int irrep_idx, OrbType type)
std::string label
Definition: DiracParser.h:44
std::vector< fermIrrep > irreps
Definition: DiracParser.h:94