QMCPACK
EinsplineSetBuilderCommon.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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
10 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 //
13 // File created by: Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 /** @file
18  *
19  * Instantiates the static data
20  * Implements member functions of EinsplineSetBuilder
21  * - EinsplineSetBuilder
22  * -
23 */
24 #include "EinsplineSetBuilder.h"
25 #include <array>
26 #include <string_view>
27 #include "OhmmsData/AttributeSet.h"
28 #include "Message/CommOperators.h"
31 #include "Particle/DistanceTable.h"
32 #include "mpi/collectives.h"
33 
34 namespace qmcplusplus
35 {
36 //std::map<H5OrbSet,SPOSet*,H5OrbSet> EinsplineSetBuilder::SPOSetMap;
37 //std::map<TinyVector<int,4>,EinsplineSetBuilder::OrbType*,Int4less> EinsplineSetBuilder::OrbitalMap;
38 ////std::map<H5OrbSet,multi_UBspline_3d_z*,H5OrbSet> EinsplineSetBuilder::ExtendedMap_z;
39 ////std::map<H5OrbSet,multi_UBspline_3d_d*,H5OrbSet> EinsplineSetBuilder::ExtendedMap_d;
40 
42  : SPOSetBuilder("spline", comm),
43  ParticleSets(psets),
44  TargetPtcl(p),
45  XMLRoot(cur),
46  Format(QMCPACK),
47  NumBands(0),
48  NumElectrons(0),
49  NumSpins(0),
50  NumTwists(0),
51  MeshFactor(1.0),
52  MeshSize(0, 0, 0),
53  twist_num_(-1),
54  LastSpinSet(-1),
55  NumOrbitalsRead(-1),
56  makeRotations(false)
57 {
58  ClassName = "EinsplineSetBuilder";
59 
60  MatchingTol = 10 * std::numeric_limits<float>::epsilon();
61  for (int i = 0; i < 3; i++)
62  for (int j = 0; j < 3; j++)
63  TileMatrix(i, j) = 0;
64 
65  //invalidate states by the basis class
66  states.clear();
67  states.resize(p.groups());
68 
69  //create vectors with nullptr
70  FullBands.resize(p.groups());
71 }
72 
73 template<typename T>
75 {
76  return TinyVector<T, 3>(round(twist[0] - 1.0e-6), round(twist[1] - 1.0e-6), round(twist[2] - 1.0e-6));
77 }
78 
79 template<typename T>
81 {
82  return twist - IntPart(twist);
83 }
84 
85 
86 EinsplineSetBuilder::~EinsplineSetBuilder() { DEBUG_MEMORY("EinsplineSetBuilder::~EinsplineSetBuilder"); }
87 
88 
90 {
91  double diff = 0.0;
92  for (int i = 0; i < OHMMS_DIM; i++)
93  for (int j = 0; j < OHMMS_DIM; j++)
94  {
95  double max_abs =
96  std::max(std::abs(SuperLattice(i, j)), static_cast<double>(std::abs(TargetPtcl.getLattice().R(i, j))));
97  if (max_abs > MatchingTol)
98  diff = std::max(diff, std::abs(SuperLattice(i, j) - TargetPtcl.getLattice().R(i, j)) / max_abs);
99  }
100 
101  if (diff > MatchingTol)
102  {
103  std::ostringstream o;
104  o.setf(std::ios::scientific, std::ios::floatfield);
105  o.precision(6);
106  o << "EinsplineSetBuilder::ReadOrbitalInfo_ESHDF \n" << "Mismatched supercell lattices.\n";
107  o << " Lattice in ESHDF5 " << std::endl;
108  o << SuperLattice << std::endl;
109  o << " Lattice in xml" << std::endl;
110  o << TargetPtcl.getLattice().R << std::endl;
111  o << " Difference " << std::endl;
112  o << SuperLattice - TargetPtcl.getLattice().R << std::endl;
113  o << " Max relative error = " << diff << std::endl;
114  o << " Tolerance = " << MatchingTol << std::endl;
115  app_error() << o.str();
116  return false;
117  }
118  return true;
119 }
120 
122 {
123  if (myComm->size() == 1)
124  return;
125  int numIons = IonTypes.size();
126  int numDensityGvecs = TargetPtcl.DensityReducedGvecs.size();
127  PooledData<double> abuffer;
128  PooledData<int> aibuffer;
129  aibuffer.add(Version.begin(), Version.end()); //myComm->bcast(Version);
130  aibuffer.add(Format);
131  abuffer.add(Lattice.begin(), Lattice.end()); //myComm->bcast(Lattice);
132  abuffer.add(RecipLattice.begin(), RecipLattice.end()); //myComm->bcast(RecipLattice);
133  abuffer.add(SuperLattice.begin(), SuperLattice.end()); //myComm->bcast(SuperLattice);
134  abuffer.add(LatticeInv.begin(), LatticeInv.end()); //myComm->bcast(LatticeInv);
135  aibuffer.add(NumBands); //myComm->bcast(NumBands);
136  aibuffer.add(NumElectrons); //myComm->bcast(NumElectrons);
137  aibuffer.add(NumSpins); //myComm->bcast(NumSpins);
138  aibuffer.add(NumTwists); //myComm->bcast(NumTwists);
139  aibuffer.add(numIons); //myComm->bcast(numIons);
140  aibuffer.add(numDensityGvecs);
141  aibuffer.add(HaveOrbDerivs);
142  myComm->bcast(abuffer);
143  myComm->bcast(aibuffer);
144  if (myComm->rank())
145  {
146  abuffer.rewind();
147  aibuffer.rewind();
148  aibuffer.get(Version.begin(), Version.end());
149  aibuffer.get(Format);
150  abuffer.get(Lattice.begin(), Lattice.end());
151  abuffer.get(RecipLattice.begin(), RecipLattice.end());
152  abuffer.get(SuperLattice.begin(), SuperLattice.end());
153  abuffer.get(LatticeInv.begin(), LatticeInv.end());
154  aibuffer.get(NumBands);
155  aibuffer.get(NumElectrons);
156  aibuffer.get(NumSpins);
157  aibuffer.get(NumTwists);
158  aibuffer.get(numIons);
159  aibuffer.get(numDensityGvecs);
160  aibuffer.get(HaveOrbDerivs);
161  TargetPtcl.DensityReducedGvecs.resize(numDensityGvecs);
162  TargetPtcl.Density_G.resize(numDensityGvecs);
163  }
164  if (IonTypes.size() != numIons)
165  {
166  IonTypes.resize(numIons);
167  IonPos.resize(numIons);
168  }
169  //new buffer
170  PooledData<double> bbuffer;
171  PooledData<int> bibuffer;
172  for (int i = 0; i < numIons; ++i)
173  bibuffer.add(IonTypes[i]);
174  //myComm->bcast(IonTypes);
175  bbuffer.add(&IonPos[0][0], &IonPos[0][0] + OHMMS_DIM * numIons);
176  //myComm->bcast(IonPos);
177  if (primcell_kpoints.size() != NumTwists)
178  primcell_kpoints.resize(NumTwists);
179  bbuffer.add(&primcell_kpoints[0][0], &primcell_kpoints[0][0] + OHMMS_DIM * NumTwists);
180  bibuffer.add(&(TargetPtcl.DensityReducedGvecs[0][0]),
181  &(TargetPtcl.DensityReducedGvecs[0][0]) + numDensityGvecs * OHMMS_DIM);
182  bbuffer.add(&(TargetPtcl.Density_G[0]), &(TargetPtcl.Density_G[0]) + numDensityGvecs);
183  myComm->bcast(bbuffer);
184  myComm->bcast(bibuffer);
185  if (myComm->rank())
186  {
187  bbuffer.rewind();
188  bibuffer.rewind();
189  for (int i = 0; i < numIons; ++i)
190  bibuffer.get(IonTypes[i]);
191  bbuffer.get(&IonPos[0][0], &IonPos[0][0] + OHMMS_DIM * numIons);
192  bbuffer.get(&primcell_kpoints[0][0], &primcell_kpoints[0][0] + OHMMS_DIM * NumTwists);
193  bibuffer.get(&(TargetPtcl.DensityReducedGvecs[0][0]),
194  &(TargetPtcl.DensityReducedGvecs[0][0]) + numDensityGvecs * OHMMS_DIM);
195  bbuffer.get(&(TargetPtcl.Density_G[0]), &(TargetPtcl.Density_G[0]) + numDensityGvecs);
196  }
197  //buffer to bcast hybrid representation atomic orbital info
198  PooledData<double> cbuffer;
199  PooledData<int> cibuffer;
200  myComm->bcast(cbuffer);
201  myComm->bcast(cibuffer);
202  AtomicCentersInfo.resize(numIons);
203  Super2Prim.resize(SourcePtcl->R.size());
206  cbuffer.add(AtomicCentersInfo.cutoff.begin(), AtomicCentersInfo.cutoff.end());
208  cibuffer.add(Super2Prim.begin(), Super2Prim.end());
209  cibuffer.add(AtomicCentersInfo.lmax.begin(), AtomicCentersInfo.lmax.end());
210  cibuffer.add(AtomicCentersInfo.GroupID.begin(), AtomicCentersInfo.GroupID.end());
212  myComm->bcast(cbuffer);
213  myComm->bcast(cibuffer);
214  if (myComm->rank())
215  {
216  cbuffer.rewind();
217  cibuffer.rewind();
220  cbuffer.get(AtomicCentersInfo.cutoff.begin(), AtomicCentersInfo.cutoff.end());
222  cibuffer.get(Super2Prim.begin(), Super2Prim.end());
223  cibuffer.get(AtomicCentersInfo.lmax.begin(), AtomicCentersInfo.lmax.end());
224  cibuffer.get(AtomicCentersInfo.GroupID.begin(), AtomicCentersInfo.GroupID.end());
226  for (int i = 0; i < numIons; i++)
228  }
229 }
230 
231 ////////////////////////////////////////////////////////////////
232 //// Create the ion ParticleSet from the data in the HDF file //
233 ////////////////////////////////////////////////////////////////
234 //void
235 //EinsplineSetBuilder::CreateIonParticleSet( std::string sourceName)
236 //{
237 // // ParticleSet &pTemp = *(new MCWalkerConfiguration);
238 // ParticleSet &pTemp = *(new ParticleSet);
239 // pTemp.setName (sourceName);
240 // SpeciesSet& tspecies(pTemp.getSpeciesSet());
241 // ParticleSets[sourceName] = &pTemp;
242 //}
243 //
244 
246 {
247  //set the primitive lattice
249 
250  for (int j = 0; j < IonPos.size(); ++j)
252 
253  IonPos.resize(SourcePtcl->getTotalNum());
255  std::copy(SourcePtcl->R.begin(), SourcePtcl->R.end(), IonPos.begin());
257 
258  //app_log() << " Primitive Cell\n";
259  //SourcePtcl->getPrimitiveLattice().print(app_log());
260  //app_log() << " Super Cell\n";
261  //SourcePtcl->Lattice.print(app_log());
262 
263  //Don't need to do this, already one by ParticleSetPool.cpp
264  // Vector<TinyVector<double, OHMMS_DIM> > primPos = IonPos;
265  // Vector<int> primTypes = IonTypes;
266  // int numCopies = std::abs(det(TileMatrix));
267  // IonTypes.resize(primPos.size()*numCopies);
268  // IonPos.resize (primPos.size()*numCopies);
269  // int maxCopies = 10;
270  // using Vec3 = TinyVector<double,3>;
271  // int index=0;
272  // for (int i0=-maxCopies; i0<=maxCopies; i0++)
273  // for (int i1=-maxCopies; i1<=maxCopies; i1++)
274  // for (int i2=-maxCopies; i2<=maxCopies; i2++)
275  // for (int iat=0; iat < primPos.size(); iat++)
276  // {
277  // Vec3 r = primPos[iat];
278  // Vec3 uPrim = PrimCell.toUnit(r);
279  // for (int i=0; i<3; i++)
280  // uPrim[i] -= std::floor(uPrim[i]);
281  // r = PrimCell.toCart(uPrim) + (double)i0*PrimCell.a(0) +
282  // (double)i1*PrimCell.a(1) + (double)i2*PrimCell.a(2);
283  // Vec3 uSuper = SuperCell.toUnit(r);
284  // if ((uSuper[0] >= -1.0e-4) && (uSuper[0] < 0.9999) &&
285  // (uSuper[1] >= -1.0e-4) && (uSuper[1] < 0.9999) &&
286  // (uSuper[2] >= -1.0e-4) && (uSuper[2] < 0.9999))
287  // {
288  // IonPos[index]= r;
289  // IonTypes[index]= primTypes[iat];
290  // index++;
291  // }
292  // }
293  // if (index != primPos.size()*numCopies)
294  // {
295  // app_error() << "The number of tiled ions, " << IonPos.size()
296  // << ", does not match the expected number of "
297  // << primPos.size()*numCopies << " or the index "<< index <<". Aborting.\n";
298  // APP_ABORT("EinsplineSetBuilder::TileIons()");
299  // }
300  // if (myComm->rank() == 0)
301  // {
302  // char buf[1000];
303  // snprintf (buf, 1000, "Supercell reduced ion positions = \n");
304  // app_log() << buf;
305  // app_log().flush();
306  // for (int i=0; i<IonPos.size(); i++)
307  // {
308  // PosType u = SuperCell.toUnit(IonPos[i]);
309  // char buf2[1000];
310  // snprintf (buf2, 1000, " %14.10f %14.10f %14.10f\n",
311  // u[0], u[1], u[2]);
312  // app_log() << buf2;
313  // app_log().flush();
314  // // IonPos[i][0], IonPos[i][1], IonPos[i][2]);
315  // }
316  // }
317 }
318 
319 
321 {
322  bool pair = true;
323  for (int n = 0; n < OHMMS_DIM; n++)
324  {
325  double d = a[n] + b[n];
326  if (std::abs(d - round(d)) > MatchingTol)
327  pair = false;
328  }
329  return pair;
330 }
331 
332 void EinsplineSetBuilder::AnalyzeTwists2(const int twist_num_inp, const TinyVector<double, OHMMS_DIM>& twist_inp)
333 {
335  for (int i = 0; i < 3; i++)
336  for (int j = 0; j < 3; j++)
337  S(i, j) = (double)TileMatrix(i, j);
338 
339  const int num_prim_kpoints = primcell_kpoints.size();
340 
341  // build a list of unique super twists that all the primitive cell k-point correspond to.
342  std::vector<PosType> superFracs; // twist super twist coordinates
343  std::vector<int>
344  superIndex; // the indices of the super twists that correpsond to all the primitive cell k-points in the unique list.
345  {
346  // scan all the primitive cell k-points
347  for (int ki = 0; ki < num_prim_kpoints; ki++)
348  {
349  PosType primTwist = primcell_kpoints[ki];
350  PosType superTwist = dot(S, primTwist);
351  PosType kp = PrimCell.k_cart(primTwist);
352  PosType ks = SuperCell.k_cart(superTwist);
353  // check the consistency of tiling, primitive and super cells.
354  if (dot(ks - kp, ks - kp) > 1.0e-6)
355  {
356  app_error() << "Primitive and super k-points do not agree. Error in coding.\n";
357  APP_ABORT("EinsplineSetBuilder::AnalyzeTwists2");
358  }
359  PosType frac = FracPart(superTwist);
360  // verify if the super twist that correpsonds to this primitive cell k-point exists in the unique list or not.
361  bool found = false;
362  for (int j = 0; j < superFracs.size(); j++)
363  {
364  PosType diff = frac - superFracs[j];
365  if (dot(diff, diff) < 1.0e-6)
366  {
367  found = true;
368  superIndex.push_back(j);
369  }
370  }
371  if (!found)
372  {
373  superIndex.push_back(superFracs.size());
374  superFracs.push_back(frac);
375  }
376  }
377  assert(superIndex.size() == num_prim_kpoints);
378  }
379 
380  const int numSuperTwists = superFracs.size();
381  {
382  app_log() << "Found " << numSuperTwists << " distinct supercell twist" << (numSuperTwists > 1 ? "s" : "")
383  << " based on " << num_prim_kpoints << " primitive cell k-point" << (num_prim_kpoints > 1 ? "s" : "")
384  << std::endl;
385  if (myComm->rank() == 0)
386  {
387  int n_tot_irred(0);
388  for (int si = 0; si < numSuperTwists; si++)
389  {
390  std::array<char, 1000> buf;
391  int length = std::snprintf(buf.data(), buf.size(), "Super twist #%d: [ %9.5f %9.5f %9.5f ]\n", si,
392  superFracs[si][0], superFracs[si][1], superFracs[si][2]);
393  if (length < 0)
394  throw std::runtime_error("Error converting Super twist to a string");
395  app_log() << std::string_view(buf.data(), length);
396  app_log().flush();
397  }
398  }
399  }
400 
401  // For each supercell twist, create a list of primitive twists which correspond to it.
402  std::vector<std::vector<int>> superSets;
403  {
404  superSets.resize(numSuperTwists);
405  for (int ki = 0; ki < num_prim_kpoints; ki++)
406  superSets[superIndex[ki]].push_back(ki);
407  }
408 
409  { // look up a super cell twist and return its index in the unique list of super cell twists.
410  std::function find_twist = [&](const TinyVector<double, OHMMS_DIM>& twist) {
411  int twist_num = -1;
412  PosType gtFrac = FracPart(twist);
413  float eps = 1e-5;
414  for (int si = 0; si < numSuperTwists; si++)
415  {
416  PosType locDiff = gtFrac - superFracs[si];
417  if (dot(locDiff, locDiff) < eps)
418  twist_num = si;
419  }
420 
421  if (twist_num < 0)
422  {
423  std::array<char, 1000> buf;
424  int length = std::
425  snprintf(buf.data(), buf.size(),
426  "AnalyzeTwists2. Input twist [ %9.5f %9.5f %9.5f] not found in the list of super twists above.\n",
427  twist[0], twist[1], twist[2]);
428  if (length < 0)
429  throw std::runtime_error("Error generating error message");
430  throw UniformCommunicateError(buf.data());
431  }
432  return twist_num;
433  };
434 
435  if (twist_inp[0] > TWIST_NO_INPUT || twist_inp[1] > TWIST_NO_INPUT || twist_inp[2] > TWIST_NO_INPUT)
436  {
437  if (twist_num_inp != TWISTNUM_NO_INPUT)
438  app_warning() << "twist attribute exists. twistnum attribute ignored. "
439  "To prevent this message, remove twistnum from input."
440  << std::endl;
441 
442  twist_num_ = find_twist(twist_inp);
443  }
444  else if (twist_num_inp != TWISTNUM_NO_INPUT)
445  {
446  app_warning() << "twist attribute does't exist but twistnum attribute was found. "
447  << "This is potentially ambiguous. Specifying twist attribute is preferred." << std::endl;
448  if (twist_num_inp < 0 || twist_num_inp >= numSuperTwists)
449  {
450  std::ostringstream msg;
451  msg << "AnalyzeTwists2. twistnum input value " << twist_num_inp << " is outside the acceptable range [0, "
452  << numSuperTwists << ")." << std::endl;
453  throw UniformCommunicateError(msg.str());
454  }
455  twist_num_ = twist_num_inp;
456  }
457  else
458  {
459  app_log() << "twist attribte does't exist. Set Gamma point." << std::endl;
460  twist_num_ = find_twist({0, 0, 0});
461  }
462 
463  assert(twist_num_ >= 0 && twist_num_ < numSuperTwists);
464 
465  std::array<char, 1000> buf;
466  int length = std::snprintf(buf.data(), buf.size(), " Using supercell twist %d: [ %9.5f %9.5f %9.5f]", twist_num_,
467  superFracs[twist_num_][0], superFracs[twist_num_][1], superFracs[twist_num_][2]);
468  if (length < 0)
469  throw std::runtime_error("Error converting supercell twist to a string");
470  app_log() << std::string_view(buf.data(), length) << std::endl;
471  }
472 
473  TargetPtcl.setTwist(superFracs[twist_num_]);
474 #ifndef QMC_COMPLEX
475  // Check to see if supercell twist is okay to use with real wave
476  // functions
477  for (int dim = 0; dim < OHMMS_DIM; dim++)
478  {
479  double t = 2.0 * superFracs[twist_num_][dim];
480  if (std::abs(t - round(t)) > MatchingTol * 100)
481  {
482  app_error() << "Cannot use this super twist with real wavefunctions.\n"
483  << "Please recompile with QMC_COMPLEX=1.\n";
484  APP_ABORT("EinsplineSetBuilder::AnalyzeTwists2");
485  }
486  }
487 #endif
488  // Now check to see that each supercell twist has the right twists
489  // to tile the primitive cell orbitals.
490  const int numTwistsNeeded = std::abs(det(TileMatrix));
491  for (int si = 0; si < numSuperTwists; si++)
492  {
493  // First make sure we have enough points
494  if (superSets[si].size() != numTwistsNeeded)
495  {
496  std::array<char, 1000> buf;
497  int length = std::snprintf(buf.data(), buf.size(), "Super twist %d should own %d k-points, but owns %d.\n", si,
498  numTwistsNeeded, static_cast<int>(superSets[si].size()));
499  if (length < 0)
500  throw std::runtime_error("Error generating Super twist string");
501  app_error() << std::string_view(buf.data(), length);
502  if (si == twist_num_)
503  {
504  APP_ABORT("EinsplineSetBuilder::AnalyzeTwists2");
505  }
506  else
507  continue;
508  }
509  // Now, make sure they are all distinct
510  int N = superSets[si].size();
511  for (int i = 0; i < N; i++)
512  {
513  PosType twistPrim_i = primcell_kpoints[superSets[si][i]];
514  PosType twistSuper_i = dot(S, twistPrim_i);
515  PosType superInt_i = IntPart(twistSuper_i);
516  for (int j = i + 1; j < N; j++)
517  {
518  PosType twistPrim_j = primcell_kpoints[superSets[si][j]];
519  PosType twistSuper_j = dot(S, twistPrim_j);
520  PosType superInt_j = IntPart(twistSuper_j);
521  if (dot(superInt_i - superInt_j, superInt_i - superInt_j) < 1.0e-6)
522  {
523  app_error() << "Identical k-points detected in super twist set " << si << std::endl;
524  APP_ABORT_TRACE(__FILE__, __LINE__, "AnalyzeTwists2");
525  }
526  }
527  }
528  }
529  app_log().flush();
530  // Finally, record which k-points to include on this group of
531  // processors, which have been assigned supercell twist twist_num_
532  IncludeTwists.clear();
533  for (int i = 0; i < superSets[twist_num_].size(); i++)
534  IncludeTwists.push_back(superSets[twist_num_][i]);
535  // Now, find out which twists are distinct
536  DistinctTwists.clear();
537 #ifndef QMC_COMPLEX
538  std::vector<int> copyTwists;
539  for (int i = 0; i < IncludeTwists.size(); i++)
540  {
541  int ti = IncludeTwists[i];
542  PosType twist_i = primcell_kpoints[ti];
543  bool distinct = true;
544  for (int j = i + 1; j < IncludeTwists.size(); j++)
545  {
546  int tj = IncludeTwists[j];
547  PosType twist_j = primcell_kpoints[tj];
548  PosType sum = twist_i + twist_j;
549  PosType diff = twist_i - twist_j;
550  if (TwistPair(twist_i, twist_j))
551  distinct = false;
552  }
553  if (distinct)
554  DistinctTwists.push_back(ti);
555  else
556  copyTwists.push_back(ti);
557  }
558  // Now determine which distinct twists require two copies
559  MakeTwoCopies.resize(DistinctTwists.size());
560  for (int i = 0; i < DistinctTwists.size(); i++)
561  {
562  MakeTwoCopies[i] = false;
563  int ti = DistinctTwists[i];
564  PosType twist_i = primcell_kpoints[ti];
565  for (int j = 0; j < copyTwists.size(); j++)
566  {
567  int tj = copyTwists[j];
568  PosType twist_j = primcell_kpoints[tj];
569  if (TwistPair(twist_i, twist_j))
570  MakeTwoCopies[i] = true;
571  }
572  if (myComm->rank() == 0)
573  {
574  std::array<char, 1000> buf;
575  int length = std::snprintf(buf.data(), buf.size(), "Using %d copies of twist angle [%6.3f, %6.3f, %6.3f]\n",
576  MakeTwoCopies[i] ? 2 : 1, twist_i[0], twist_i[1], twist_i[2]);
577  if (length < 0)
578  throw std::runtime_error("Error generating string");
579  app_log() << std::string_view(buf.data(), length);
580  app_log().flush();
581  }
582  }
583  // Find out if we can make real orbitals
584  use_real_splines_ = true;
585  for (int i = 0; i < DistinctTwists.size(); i++)
586  {
587  int ti = DistinctTwists[i];
588  PosType twist = primcell_kpoints[ti];
589  for (int j = 0; j < OHMMS_DIM; j++)
590  if (std::abs(twist[j] - 0.0) > MatchingTol && std::abs(twist[j] - 0.5) > MatchingTol &&
591  std::abs(twist[j] + 0.5) > MatchingTol)
592  use_real_splines_ = false;
593  }
594  if (use_real_splines_ && (DistinctTwists.size() > 1))
595  {
596  app_log() << "***** Use of real orbitals is possible, but not currently implemented\n"
597  << " with more than one twist angle.\n";
598  use_real_splines_ = false;
599  }
600  if (use_real_splines_)
601  app_log() << "Using real splines.\n";
602  else
603  app_log() << "Using complex splines.\n";
604 #else
605  DistinctTwists.resize(IncludeTwists.size());
606  MakeTwoCopies.resize(IncludeTwists.size());
607  for (int i = 0; i < IncludeTwists.size(); i++)
608  {
610  MakeTwoCopies[i] = false;
611  }
612  use_real_splines_ = false;
613 #endif
614 }
615 
616 
617 void EinsplineSetBuilder::OccupyBands(int spin, int sortBands, int numOrbs, bool skipChecks)
618 {
619  if (myComm->rank() != 0)
620  return;
621  if (spin >= NumSpins && !skipChecks)
622  {
623  app_error() << "To developer: User is requesting for orbitals in an invalid spin group " << spin
624  << ". Current h5 file only contains spin groups " << "[0.." << NumSpins - 1 << "]." << std::endl;
625  app_error() << "To user: Orbital H5 file contains no spin down data and is appropriate only for spin unpolarized "
626  "calculations. "
627  << "If this is your intent, please replace 'spindataset=1' with 'spindataset=0' in the input file."
628  << std::endl;
629  abort();
630  }
631  if (Format == ESHDF)
632  {
633  OccupyBands_ESHDF(spin, sortBands, numOrbs);
634  return;
635  }
636  std::string eigenstatesGroup;
637  if (Version[0] == 0 && Version[1] == 11)
638  eigenstatesGroup = "/eigenstates_3";
639  else if (Version[0] == 0 && Version[1] == 20)
640  eigenstatesGroup = "/eigenstates";
641 
642  if (FullBands[spin]->size())
643  {
644  app_log() << " FullBand[" << spin << "] exists. Reuse it. " << std::endl;
645  return;
646  }
647 
648  std::vector<BandInfo>& SortBands(*FullBands[spin]);
649 
650  SortBands.clear();
651  for (int ti = 0; ti < DistinctTwists.size(); ti++)
652  {
653  int tindex = DistinctTwists[ti];
654  // First, read valence states
655  for (int bi = 0; bi < NumBands; bi++)
656  {
657  BandInfo band;
658  band.TwistIndex = tindex;
659  band.BandIndex = bi;
660  band.MakeTwoCopies = MakeTwoCopies[ti];
661  // Read eigenenergy from file
662  std::ostringstream ePath, sPath;
663  if ((Version[0] == 0 && Version[1] == 11) || NumTwists > 1)
664  {
665  ePath << eigenstatesGroup << "/twist_" << tindex << "/band_" << bi << "/eigenvalue";
666  sPath << eigenstatesGroup << "/twist_" << tindex << "/band_" << bi << "/spin";
667  }
668  else if (NumBands > 1)
669  {
670  ePath << eigenstatesGroup << "/twist/band_" << bi << "/eigenvalue";
671  sPath << eigenstatesGroup << "/twist/band_" << bi << "/spin";
672  }
673  else
674  {
675  ePath << eigenstatesGroup << "/twist/band/eigenvalue";
676  sPath << eigenstatesGroup << "/twist/band/spin";
677  }
678  band.Energy = -1.01e100;
679  H5File.read(band.Energy, ePath.str());
680  if (band.Energy > -1.0e100)
681  {
682  H5File.read(band.Spin, sPath.str());
683  if (band.Spin == spin)
684  SortBands.push_back(band);
685  }
686  }
687  }
688  int orbIndex = 0;
689  int numOrbs_counter = 0;
690  while (numOrbs_counter < numOrbs)
691  {
692  if (SortBands[orbIndex].MakeTwoCopies)
693  numOrbs_counter += 2;
694  else
695  numOrbs_counter++;
696  orbIndex++;
697  }
698  NumDistinctOrbitals = orbIndex;
699  app_log() << "We will read " << NumDistinctOrbitals << " distinct orbitals.\n";
700 }
701 
702 void EinsplineSetBuilder::bcastSortBands(int spin, int n, bool root)
703 {
704  std::vector<BandInfo>& SortBands(*FullBands[spin]);
705 
706  TinyVector<int, 2> nbands(int(SortBands.size()), n);
707  mpi::bcast(*myComm, nbands);
708 
709  //buffer to serialize BandInfo
710  PooledData<OHMMS_PRECISION_FULL> misc(nbands[0] * 4);
711  n = NumDistinctOrbitals = nbands[1];
712 
713  if (root)
714  {
715  misc.rewind();
716  for (int i = 0; i < n; ++i)
717  {
718  misc.put(SortBands[i].TwistIndex);
719  misc.put(SortBands[i].BandIndex);
720  misc.put(SortBands[i].Energy);
721  misc.put(SortBands[i].MakeTwoCopies);
722  }
723 
724  for (int i = n; i < SortBands.size(); ++i)
725  {
726  misc.put(SortBands[i].TwistIndex);
727  misc.put(SortBands[i].BandIndex);
728  misc.put(SortBands[i].Energy);
729  misc.put(SortBands[i].MakeTwoCopies);
730  }
731  }
732  myComm->bcast(misc);
733 
734  if (!root)
735  {
736  SortBands.resize(nbands[0]);
737  misc.rewind();
738  for (int i = 0; i < n; ++i)
739  {
740  misc.get(SortBands[i].TwistIndex);
741  misc.get(SortBands[i].BandIndex);
742  misc.get(SortBands[i].Energy);
743  misc.get(SortBands[i].MakeTwoCopies);
744  }
745  for (int i = n; i < SortBands.size(); ++i)
746  {
747  misc.get(SortBands[i].TwistIndex);
748  misc.get(SortBands[i].BandIndex);
749  misc.get(SortBands[i].Energy);
750  misc.get(SortBands[i].MakeTwoCopies);
751  }
752  }
753 }
754 
755 } // namespace qmcplusplus
void resize(size_type n, Type_t val=Type_t())
Resize the container.
Definition: OhmmsVector.h:166
a class that defines a supercell in D-dimensional Euclean space.
bool TwistPair(PosType a, PosType b) const
double Energy
energy associated with this band
Definition: BandInfo.h:37
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
Tensor< int, OHMMS_DIM > TileMatrix
std::ostream & app_warning()
Definition: OutputManager.h:69
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
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)
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
ParticleSet & TargetPtcl
quantum particle set
TinyVector< T, 3 > FracPart(const TinyVector< T, 3 > &twist)
std::vector< TinyVector< double, OHMMS_DIM > > ion_pos
int BandIndex
band index
Definition: BandInfo.h:31
std::ostream & app_error()
Definition: OutputManager.h:67
Builder class for einspline-based SPOSet objects.
void OccupyBands_ESHDF(int spin, int sortBands, int numOrbs)
struct qmcplusplus::EinsplineSetBuilder::CenterInfo AtomicCentersInfo
ParticleSet * SourcePtcl
ionic system
std::vector< std::unique_ptr< SPOSetInfo > > states
state info of all possible states available in the basis
Definition: SPOSetBuilder.h:57
void rewind(size_type cur=0)
set the Current to a cursor
Definition: PooledData.h:56
int size() const
return the number of tasks
Definition: Communicate.h:118
void AnalyzeTwists2(const int twist_num_inp, const TinyVector< double, OHMMS_DIM > &twist_inp)
analyze twists of orbitals in h5 and determinine twist_num_
#define OHMMS_DIM
Definition: config.h:64
std::vector< std::unique_ptr< std::vector< BandInfo > > > FullBands
Helper vector for sorting bands.
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
Wrapping information on parallelism.
Definition: Communicate.h:68
bool HaveOrbDerivs
This is true if we have the orbital derivatives w.r.t. the ion positions.
int groups() const
return the number of groups
Definition: ParticleSet.h:511
TinyVector< T, 3 > IntPart(const TinyVector< T, 3 > &twist)
Vector< TinyVector< double, OHMMS_DIM > > IonPos
SingleParticlePos k_cart(const SingleParticlePos &kin) const
conversion of a reciprocal-vector
void bcast(T &a, Communicate *comm)
Definition: CommUtilities.h:78
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
base class for the real SPOSet builder
Definition: SPOSetBuilder.h:47
size_type size() const
return the current size
Definition: OhmmsVector.h:162
static constexpr double TWIST_NO_INPUT
twist_inp[i] <= -9999 to indicate no given input after parsing XML
void add(T &x)
Definition: PooledData.h:88
void bcastSortBands(int splin, int N, bool root)
broadcast SortBands
base class to read data and manage spline tables
Communicate * myComm
pointer to Communicate
Definition: MPIObjectBase.h:62
This a subclass for runtime errors that will occur on all ranks.
std::vector< ComplexType > Density_G
Definition: ParticleSet.h:98
std::map< std::string, const std::unique_ptr< ParticleSet > > PSetMap
std::string ClassName
class Name
Definition: MPIObjectBase.h:65
void get(T &x)
Definition: PooledData.h:131
ParticlePos R
Position.
Definition: ParticleSet.h:79
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
bool MakeTwoCopies
This is true if we should make distinct copies represeninting a +k, -k pair.
Definition: BandInfo.h:39
void setTwist(const SingleParticlePos &t)
Definition: ParticleSet.h:481
void OccupyBands(int spin, int sortBands, int numOrbs, bool skipChecks=false)
static constexpr int TWISTNUM_NO_INPUT
twistnum_inp == -9999 to indicate no given input after parsing XML
#define DEBUG_MEMORY(msg)
Definition: Configuration.h:31
int TwistIndex
twist index
Definition: BandInfo.h:29
void put(T &x)
Definition: PooledData.h:172
Tensor< double, OHMMS_DIM > LatticeInv
Tensor< double, OHMMS_DIM > SuperLattice
const auto & getLattice() const
Definition: ParticleSet.h:251
std::vector< TinyVector< double, OHMMS_DIM > > primcell_kpoints
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
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
void bcast(T &)
#define APP_ABORT_TRACE(f, l, msg)
Definition: AppAbort.h:34
Type_t * begin()
Definition: Tensor.h:269
Tensor< double, OHMMS_DIM > RecipLattice
EinsplineSetBuilder(ParticleSet &p, const PSetMap &psets, Communicate *comm, xmlNodePtr cur)
constructor
std::vector< TinyVector< int, OHMMS_DIM > > DensityReducedGvecs
Particle density in G-space for MPC interaction.
Definition: ParticleSet.h:97
bool use_real_splines_
if false, splines are conceptually complex valued
int Spin
spin index
Definition: BandInfo.h:35
auto & getPrimitiveLattice() const
Definition: ParticleSet.h:252
Type_t * end()
Definition: Tensor.h:271