QMCPACK
SplineSetReader.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) 2023 QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
10 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 // Jeongnim Kim, jeongnim.kim@inte.com, Intel Corp.
12 //
13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 #include "SplineSetReader.h"
18 #include "OneSplineOrbData.hpp"
19 #include "Utilities/FairDivide.h"
20 #include "einspline_helper.hpp"
21 #include <Timer.h>
22 #if defined(QMC_COMPLEX)
23 #include "SplineC2C.h"
24 #include "SplineC2COMPTarget.h"
25 #else
26 #include "SplineR2R.h"
27 #include "SplineC2R.h"
28 #include "SplineC2ROMPTarget.h"
29 #endif
30 
31 namespace qmcplusplus
32 {
33 template<typename SA>
35 {}
36 
37 template<typename SA>
38 std::unique_ptr<SPOSet> SplineSetReader<SA>::create_spline_set(const std::string& my_name,
39  int spin,
40  const BandInfoGroup& bandgroup)
41 {
42  auto bspline = std::make_unique<SA>(my_name);
43  app_log() << " ClassName = " << bspline->getClassName() << std::endl;
44  bool foundspline = createSplineDataSpaceLookforDumpFile(bandgroup, *bspline);
45  if (foundspline)
46  {
47  Timer now;
48  hdf_archive h5f(myComm);
49  const auto splinefile = getSplineDumpFileName(bandgroup);
50  h5f.open(splinefile, H5F_ACC_RDONLY);
51  foundspline = bspline->read_splines(h5f);
52  if (foundspline)
53  app_log() << " Successfully restored 3D B-spline coefficients from " << splinefile << ". The reading time is "
54  << now.elapsed() << " sec." << std::endl;
55  }
56 
57  if (!foundspline)
58  {
59  bspline->flush_zero();
60 
61  Timer now;
62  initialize_spline_pio_gather(spin, bandgroup, *bspline);
63  app_log() << " SplineSetReader initialize_spline_pio " << now.elapsed() << " sec" << std::endl;
64 
65  if (saveSplineCoefs && myComm->rank() == 0)
66  {
67  Timer now;
68  const std::string splinefile(getSplineDumpFileName(bandgroup));
69  hdf_archive h5f;
70  h5f.create(splinefile);
71  std::string classname = bspline->getClassName();
72  h5f.write(classname, "class_name");
73  int sizeD = sizeof(typename SA::DataType);
74  h5f.write(sizeD, "sizeof");
75  bspline->write_splines(h5f);
76  h5f.close();
77  app_log() << " Stored spline coefficients in " << splinefile << " for potential reuse. The writing time is "
78  << now.elapsed() << " sec." << std::endl;
79  }
80  }
81 
82  {
83  Timer now;
84  bspline->bcast_tables(myComm);
85  app_log() << " Time to bcast the table = " << now.elapsed() << std::endl;
86  }
87 
88  return bspline;
89 }
90 
91 template<typename SA>
93 {
94  if (bspline.isComplex())
95  app_log() << " Using complex einspline table" << std::endl;
96  else
97  app_log() << " Using real einspline table" << std::endl;
98 
99  //baseclass handles twists
100  check_twists(bspline, bandgroup);
101 
102  Ugrid xyz_grid[3];
103 
104  typename SA::BCType xyz_bc[3];
105  bool havePsig = set_grid(bspline.HalfG, xyz_grid, xyz_bc);
106  if (!havePsig)
107  myComm->barrier_and_abort("SplineSetReader needs psi_g. Set precision=\"double\".");
108  bspline.create_spline(xyz_grid, xyz_bc);
109 
110  int foundspline = 0;
111  Timer now;
112  if (myComm->rank() == 0)
113  {
114  now.restart();
115  hdf_archive h5f(myComm);
116  foundspline = h5f.open(getSplineDumpFileName(bandgroup), H5F_ACC_RDONLY);
117  if (foundspline)
118  {
119  std::string aname("none");
120  foundspline = h5f.readEntry(aname, "class_name");
121  foundspline = (aname.find(bspline.getKeyword()) != std::string::npos);
122  }
123  if (foundspline)
124  {
125  int sizeD = 0;
126  foundspline = h5f.readEntry(sizeD, "sizeof");
127  foundspline = (sizeD == sizeof(typename SA::DataType));
128  }
129  h5f.close();
130  }
131  myComm->bcast(foundspline);
132  return foundspline;
133 }
134 
135 template<typename SA>
137  hdf_archive& h5f,
138  Vector<std::complex<double>>& cG) const
139 {
140  if (!h5f.readEntry(cG, s))
141  {
142  std::ostringstream msg;
143  msg << "SplineSetReader Failed to read band(s) from h5 file. " << "Attempted dataset " << s << " with " << cG.size()
144  << " complex numbers." << std::endl;
145  throw std::runtime_error(msg.str());
146  }
147  double total_norm = compute_norm(cG);
148  if ((checkNorm) && (std::abs(total_norm - 1.0) > PW_COEFF_NORM_TOLERANCE))
149  {
150  std::ostringstream msg;
151  msg << "SplineSetReader The orbital dataset " << s << " has a wrong norm " << total_norm
152  << ", computed from plane wave coefficients!" << std::endl
153  << "This may indicate a problem with the HDF5 library versions used "
154  << "during wavefunction conversion or read." << std::endl;
155  throw std::runtime_error(msg.str());
156  }
157 }
158 
159 template<typename SA>
161  const BandInfoGroup& bandgroup,
162  SA& bspline) const
163 {
164  //distribute bands over processor groups
165  int Nbands = bandgroup.getNumDistinctOrbitals();
166  const int Nprocs = myComm->size();
167  const int Nbandgroups = std::min(Nbands, Nprocs);
168  Communicate band_group_comm(*myComm, Nbandgroups);
169  std::vector<int> band_groups(Nbandgroups + 1, 0);
170  FairDivideLow(Nbands, Nbandgroups, band_groups);
171  int iorb_first = band_groups[band_group_comm.getGroupID()];
172  int iorb_last = band_groups[band_group_comm.getGroupID() + 1];
173 
174  app_log() << "Start transforming plane waves to 3D B-Splines." << std::endl;
175  OneSplineOrbData oneband(mybuilder->MeshSize, bspline.HalfG, bspline.isComplex());
176  hdf_archive h5f(&band_group_comm, false);
177  Vector<std::complex<double>> cG(mybuilder->Gvecs[0].size());
178  const std::vector<BandInfo>& cur_bands = bandgroup.myBands;
179  if (band_group_comm.isGroupLeader())
180  {
181  h5f.open(mybuilder->H5FileName, H5F_ACC_RDONLY);
182  for (int iorb = iorb_first; iorb < iorb_last; iorb++)
183  {
184  const auto& cur_band = cur_bands[bspline.BandIndexMap[iorb]];
185  const int ti = cur_band.TwistIndex;
186  readOneOrbitalCoefs(psi_g_path(ti, spin, cur_band.BandIndex), h5f, cG);
187  oneband.fft_spline(cG, mybuilder->Gvecs[0], mybuilder->primcell_kpoints[ti], rotate);
188  bspline.set_spline(&oneband.get_spline_r(), &oneband.get_spline_i(), cur_band.TwistIndex, iorb, 0);
189  }
190 
191  {
192  band_group_comm.getGroupLeaderComm()->barrier();
193  Timer now;
194  bspline.gather_tables(band_group_comm.getGroupLeaderComm());
195  app_log() << " Time to gather the table = " << now.elapsed() << std::endl;
196  }
197  }
198 }
199 
200 #if defined(QMC_COMPLEX)
201 template class SplineSetReader<SplineC2C<float>>;
203 #if !defined(QMC_MIXED_PRECISION)
204 template class SplineSetReader<SplineC2C<double>>;
206 #endif
207 #else
208 template class SplineSetReader<SplineC2R<float>>;
209 template class SplineSetReader<SplineR2R<float>>;
211 #if !defined(QMC_MIXED_PRECISION)
212 template class SplineSetReader<SplineC2R<double>>;
213 template class SplineSetReader<SplineR2R<double>>;
215 #endif
216 #endif
217 } // namespace qmcplusplus
double bspline(double x, const std::vector< double > &t, const std::vector< double > &c, int k)
double elapsed() const
Definition: Timer.h:30
void restart()
Definition: Timer.h:29
void barrier() const
void write(T &data, const std::string &aname)
write the data to the group aname and check status runtime error is issued on I/O error ...
Definition: hdf_archive.h:259
bool open(const std::filesystem::path &fname, unsigned flags=H5F_ACC_RDWR)
open a file
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
std::ostream & app_log()
Definition: OutputManager.h:65
void close()
close all the open groups and file
Definition: hdf_archive.cpp:38
class to handle hdf file
Definition: hdf_archive.h:51
Timer class.
T min(T a, T b)
void FairDivideLow(int ntot, int npart, IV &adist)
partition ntot elements among npart
Definition: FairDivide.h:114
T compute_norm(const Vector< std::complex< T >> &cG)
Compute the norm of an orbital.
int getNumDistinctOrbitals() const
return the size of this band
Definition: BandInfo.h:85
Wrapping information on parallelism.
Definition: Communicate.h:68
Each SplineC2X needs a reader derived from BsplineReader.
Definition: BsplineReader.h:39
int getGroupID() const
return the group id
Definition: Communicate.h:121
General SplineSetReader to handle any unitcell.
a group of bands
Definition: BandInfo.h:66
A collection of functions for dividing fairly.
class to handle complex splines to real orbitals with splines of arbitrary precision ...
SplineSetReader(EinsplineSetBuilder *e)
bool isGroupLeader()
return true if the current MPI rank is the group lead
Definition: Communicate.h:134
class to handle complex splines to real orbitals with splines of arbitrary precision splines storage ...
bool create(const std::filesystem::path &fname, unsigned flags=H5F_ACC_TRUNC)
create a file
The most general reader class for the following classes using the full single grid for the supercell...
class to handle complex splines to complex orbitals with splines of arbitrary precision splines stora...
Communicate * getGroupLeaderComm()
Definition: Communicate.h:230
#define PW_COEFF_NORM_TOLERANCE
bool readEntry(T &data, const std::string &aname)
read the data from the group aname and return status use read() for inbuilt error checking ...
Definition: hdf_archive.h:293
class to handle complex splines to complex orbitals with splines of arbitrary precision ...
std::vector< BandInfo > myBands
Bands that belong to this group.
Definition: BandInfo.h:79