QMCPACK
HDFWalkerOutput.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: D.C. Yang, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Cynthia Gu, zg1@ornl.gov, Oak Ridge National Laboratory
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 //
13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 /** @file
18  * @brief definition of HDFWalkerOuput and other support class and functions
19  */
20 #include "HDFWalkerOutput.h"
22 #include "OhmmsData/FileUtility.h"
23 #include "hdf/HDFVersion.h"
24 #include <numeric>
25 #include <iostream>
26 #include <sstream>
27 #include "Message/Communicate.h"
28 #include "mpi/collectives.h"
29 #include "hdf/hdf_hyperslab.h"
30 
31 namespace qmcplusplus
32 {
33 /* constructor
34  * @param W walkers to operate on
35  * @param aroot the root file name
36  * @param c communicator
37  *
38  * Create the HDF5 file "aroot.config.h5" for output.
39  * Constructor is responsible to create a hdf5 file and create basic groups
40  * so that subsequent write can utilize existing dataspaces.
41  * HDF5 contains
42  * - state_0
43  * -- block
44  * -- number of walkers
45  * -- walker_partition
46  * -- walker_weights
47  * -- walkers
48  * - config_collection
49  * -- NumOfConfigurations current count of the configurations
50  * -- config0000 current configuration
51  * -- config#### configuration for each block
52  * Other classes can add datasets as needed.
53  * open/close functions are provided so that the hdf5 file is closed during
54  * the life time of this object. This is necessary so that failures do not lead
55  * to unclosed hdf5.
56  */
57 HDFWalkerOutput::HDFWalkerOutput(size_t num_ptcls, const std::string& aroot, Communicate* c)
58  : appended_blocks(0),
59  number_of_walkers_(0),
60  number_of_particles_(num_ptcls),
61  myComm(c),
62  currentConfigNumber(0),
63  RootName(aroot)
64 {
65  block = -1;
66 }
67 
68 /** Destructor writes the state of random numbers and close the file */
70 
71 /** Write the set of walker configurations to the HDF5 file.
72  * @param W set of walker configurations
73  *
74  * Dump is for restart and do not preserve the file
75  * - version
76  * - state_0
77  * - block (int)
78  * - number_of_walkers (int)
79  * - walker_partition (int array)
80  * - walkers (nw,np,3)
81  */
82 bool HDFWalkerOutput::dump(const WalkerConfigurations& W, int nblock)
83 {
84  std::filesystem::path FileName = myComm->getName();
85  FileName.concat(hdf::config_ext);
86  //rotate files
87  //if(!myComm->rank() && currentConfigNumber)
88  //{
89  // std::ostringstream o;
90  // o<<myComm->getName()<<".b"<<(currentConfigNumber%5) << hdf::config_ext;
91  // rename(prevFile.c_str(),o.str().c_str());
92  //}
93 
94  //try to use collective
95  hdf_archive dump_file(myComm, true);
96  dump_file.create(FileName);
97  HDFVersion cur_version;
98  dump_file.write(cur_version.version, hdf::version);
99  dump_file.push(hdf::main_state);
100  dump_file.write(nblock, "block");
101 
102  write_configuration(W, dump_file, nblock);
103  dump_file.close();
104 
106  prevFile = FileName;
107  return true;
108 }
109 
111 {
112  const int wb = OHMMS_DIM * number_of_particles_;
113  if (nblock > block)
114  {
115  RemoteData[0].resize(wb * W.getActiveWalkers());
116  RemoteDataW[0].resize(W.getActiveWalkers());
117  W.putConfigurations(RemoteData[0].data(), RemoteDataW[0].data());
118  block = nblock;
119  }
120 
121  auto& walker_offsets = W.getWalkerOffsets();
122  number_of_walkers_ = walker_offsets[myComm->size()];
124 
125  if (hout.is_parallel())
126  {
127  { // write walker offset.
128  // Though it is a small array, it needs to be written collectively in large scale runs.
129  std::array<size_t, 1> gcounts{static_cast<size_t>(myComm->size()) + 1};
130  std::array<size_t, 1> counts{0};
131  std::array<size_t, 1> offsets{static_cast<size_t>(myComm->rank())};
132  std::vector<int> myWalkerOffset;
133  if (myComm->size() - 1 == myComm->rank())
134  {
135  counts[0] = 2;
136  myWalkerOffset.push_back(walker_offsets[myComm->rank()]);
137  myWalkerOffset.push_back(walker_offsets[myComm->size()]);
138  }
139  else
140  {
141  counts[0] = 1;
142  myWalkerOffset.push_back(walker_offsets[myComm->rank()]);
143  }
144  hyperslab_proxy<std::vector<int>, 1> slab(myWalkerOffset, gcounts, counts, offsets);
145  hout.write(slab, "walker_partition");
146  }
147  { // write walker configuration
148  std::array<size_t, 3> gcounts{number_of_walkers_, number_of_particles_, OHMMS_DIM};
149  std::array<size_t, 3> counts{W.getActiveWalkers(), number_of_particles_, OHMMS_DIM};
150  std::array<size_t, 3> offsets{static_cast<size_t>(walker_offsets[myComm->rank()]), 0, 0};
151  hyperslab_proxy<BufferType, 3> slab(RemoteData[0], gcounts, counts, offsets);
152  hout.write(slab, hdf::walkers);
153  }
154  {
155  std::array<size_t, 1> gcounts{number_of_walkers_};
156  std::array<size_t, 1> counts{W.getActiveWalkers()};
157  std::array<size_t, 1> offsets{static_cast<size_t>(walker_offsets[myComm->rank()])};
158  hyperslab_proxy<std::vector<QMCTraits::FullPrecRealType>, 1> slab(RemoteDataW[0], gcounts, counts, offsets);
159  hout.write(slab, hdf::walker_weights);
160  }
161  }
162  else
163  { //gaterv to the master and master writes it, could use isend/irecv
164  hout.write(walker_offsets, "walker_partition");
165  if (myComm->size() > 1)
166  {
167  std::vector<int> displ(myComm->size()), counts(myComm->size());
168  for (int i = 0; i < myComm->size(); ++i)
169  {
170  counts[i] = wb * (walker_offsets[i + 1] - walker_offsets[i]);
171  displ[i] = wb * walker_offsets[i];
172  }
173  if (!myComm->rank())
174  RemoteData[1].resize(wb * walker_offsets[myComm->size()]);
175  mpi::gatherv(*myComm, RemoteData[0], RemoteData[1], counts, displ);
176  // update counts and displ for gathering walker weights
177  for (int i = 0; i < myComm->size(); ++i)
178  {
179  counts[i] = (walker_offsets[i + 1] - walker_offsets[i]);
180  displ[i] = walker_offsets[i];
181  }
182  if (!myComm->rank())
183  RemoteDataW[1].resize(walker_offsets[myComm->size()]);
184  mpi::gatherv(*myComm, RemoteDataW[0], RemoteDataW[1], counts, displ);
185  }
186  int buffer_id = (myComm->size() > 1) ? 1 : 0;
187  {
188  std::array<size_t, 3> gcounts{number_of_walkers_, number_of_particles_, OHMMS_DIM};
189  hout.writeSlabReshaped(RemoteData[buffer_id], gcounts, hdf::walkers);
190  }
191  {
192  std::array<size_t, 1> gcounts{number_of_walkers_};
193  hout.writeSlabReshaped(RemoteDataW[buffer_id], gcounts, hdf::walker_weights);
194  }
195  }
196 }
197 } // namespace qmcplusplus
bool dump(const WalkerConfigurations &w, int block)
dump configurations
std::array< BufferType, 2 > RemoteData
const size_t number_of_particles_
number of particles
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
std::array< std::vector< QMCTraits::FullPrecRealType >, 2 > RemoteDataW
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
size_t getActiveWalkers() const
return the number of active walkers
Communicate * myComm
communicator
class to use file space hyperslab with a serialized container
Definition: hdf_hyperslab.h:35
A set of light weight walkers that are carried between driver sections and restart.
const char num_walkers[]
Definition: HDFVersion.h:37
void close()
close all the open groups and file
Definition: hdf_archive.cpp:38
const char walker_weights[]
Definition: HDFVersion.h:38
class to handle hdf file
Definition: hdf_archive.h:51
const char walkers[]
Definition: HDFVersion.h:36
int size() const
return the number of tasks
Definition: Communicate.h:118
#define OHMMS_DIM
Definition: config.h:64
bool is_parallel() const
return true if parallel i/o
Definition: hdf_archive.h:120
Wrapping information on parallelism.
Definition: Communicate.h:68
const std::string & getName() const
Definition: Communicate.h:131
const char config_ext[]
extension of a configuration file
Definition: HDFVersion.h:27
void writeSlabReshaped(T &data, const std::array< IT, RANK > &shape, const std::string &aname)
write the container data with a specific shape and check status
Definition: hdf_archive.h:274
const char main_state[]
Definition: HDFVersion.h:31
HDFWalkerOutput(size_t num_ptcls, const std::string &fname, Communicate *c)
constructor
void push(const std::string &gname, bool createit=true)
push a group to the group stack
const std::vector< int > & getWalkerOffsets() const
bool create(const std::filesystem::path &fname, unsigned flags=H5F_ACC_TRUNC)
create a file
void putConfigurations(Walker_t::RealType *target, QMCTraits::FullPrecRealType *weights) const
save the particle positions of all the walkers into target
void gatherv(T *sb, T *rb, int n, IT &counts, IT &displ, int dest)
void write_configuration(const WalkerConfigurations &W, hdf_archive &hout, int block)
const char version[]
Definition: HDFVersion.h:30
size_t number_of_walkers_
number of walkers when a state is dumped