QMCPACK
WalkerReconfigurationMPI.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: 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 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
10 // Andrew D. Baczewski, adbacze@sandia.gov, Sandia National Laboratories
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
19 #include "Utilities/FairDivide.h"
21 
22 namespace qmcplusplus
23 {
25 
26 
27 /** default constructor
28  *
29  * set SwapMode
30  */
32 {
33  SwapMode = 1;
34 }
35 
37 {
38  int nwkept = swapWalkers(W);
39  measureProperties(iter);
41  //RealType wgtInv(1.0/curData[WEIGHT_INDEX]);
42  //accumData[ENERGY_INDEX] += curData[ENERGY_INDEX]*wgtInv;
43  //accumData[ENERGY_SQ_INDEX] += curData[ENERGY_SQ_INDEX]*wgtInv;
44  //accumData[WALKERSIZE_INDEX] += nwkept;
45  ////accumData[WALKERSIZE_INDEX] += curData[WALKERSIZE_INDEX];
46  //accumData[WEIGHT_INDEX] += curData[WEIGHT_INDEX];
47  //set Weight and Multiplicity to default values
48  MCWalkerConfiguration::iterator it(W.begin()), it_end(W.end());
49  while (it != it_end)
50  {
51  (*it)->Weight = 1.0;
52  (*it)->Multiplicity = 1.0;
53  ++it;
54  }
55  return nwkept;
56 }
57 
59 {
60  //ostringstream o;
61  //o << "check." << MyContext << ".dat";
62  //ofstream fout(o.str().c_str(),std::ios::app);
63  int nw = W.getActiveWalkers();
64  if (TotalWalkers != nw * num_contexts_)
65  {
66  FirstWalker = nw * MyContext;
67  LastWalker = FirstWalker + nw;
69  nwInv = 1.0 / static_cast<FullPrecRealType>(TotalWalkers);
70  ncopy_w.resize(nw);
71  wConf.resize(nw);
72  //wSum.resize(NumContexts);
73  wOffset.resize(num_contexts_ + 1);
74  dN.resize(num_contexts_ + 4);
75  }
76  UnitZeta = Random();
79  //std::fill(wSum.begin(),wSum.end(),0.0);
80  MCWalkerConfiguration::iterator it(W.begin()), it_end(W.end());
81  int iw = 0;
82  FullPrecRealType esum = 0.0, e2sum = 0.0, wtot = 0.0, ecum = 0.0;
83  FullPrecRealType r2_accepted = 0.0, r2_proposed = 0.0;
84  while (it != it_end)
85  {
86  r2_accepted += (*it)->Properties(WP::R2ACCEPTED);
87  r2_proposed += (*it)->Properties(WP::R2PROPOSED);
88  FullPrecRealType wgt((*it)->Weight);
89  FullPrecRealType e((*it)->Properties(WP::LOCALENERGY));
90  esum += wgt * e;
91  e2sum += wgt * e * e;
92  wtot += wgt;
93  ecum += e;
94  wConf[iw++] = wgt;
95  ++it;
96  }
97  //wSum[MyContext]=wtot;
98  curData[ENERGY_INDEX] = esum;
99  curData[ENERGY_SQ_INDEX] = e2sum;
101  curData[WEIGHT_INDEX] = wtot;
102  curData[EREF_INDEX] = ecum;
103  curData[R2ACCEPTED_INDEX] = r2_accepted;
104  curData[R2PROPOSED_INDEX] = r2_proposed;
105  std::fill(curData.begin() + LE_MAX, curData.end(), 0.0);
106  curData[LE_MAX + MyContext] = wtot;
107  //collect everything
109  //update EnsembleProperty
112  //wOffset[ip] is the partial sum update to ip
113  wOffset[0] = 0;
114  //for(int ip=0; ip<NumContexts; ip++) wOffset[ip+1]=wOffset[ip]+wSum[ip];
115  for (int ip = 0, jp = LE_MAX; ip < num_contexts_; ip++, jp++)
116  wOffset[ip + 1] = wOffset[ip] + curData[jp];
117  wtot = wOffset[num_contexts_]; //wtot is the total weight
118  //find the lower and upper bound of index
119  int minIndex =
120  static_cast<int>((wOffset[MyContext] / wtot - DeltaStep) * static_cast<FullPrecRealType>(TotalWalkers)) - 1;
121  int maxIndex =
122  static_cast<int>((wOffset[MyContext + 1] / wtot - DeltaStep) * static_cast<FullPrecRealType>(TotalWalkers)) + 1;
123  int nb = maxIndex - minIndex + 1;
124  std::vector<FullPrecRealType> Zeta(nb);
125  for (int i = minIndex, ii = 0; i < maxIndex; i++, ii++)
126  {
127  Zeta[ii] = wtot * (DeltaStep + static_cast<FullPrecRealType>(i) * nwInv);
128  }
130  int ind = 0;
131  while (Zeta[ind] < wCur)
132  {
133  ind++;
134  }
135  //surviving walkers
136  int icdiff = 0;
137  for (iw = 0; iw < nw; iw++)
138  {
139  FullPrecRealType tryp = wCur + std::abs(wConf[iw]);
140  int ni = 0;
141  while (Zeta[ind] < tryp && Zeta[ind] >= wCur)
142  {
143  ind++;
144  ni++;
145  }
146  wCur += std::abs(wConf[iw]);
147  if (ni)
148  {
149  icdiff++;
150  }
151  ncopy_w[iw] = ni;
152  }
153  //plus: a list of walkers to be duplicated
154  //minus: a list of walkers to be removed
155  std::vector<int> plus, minus;
156  for (iw = 0; iw < nw; iw++)
157  {
158  int m = ncopy_w[iw];
159  if (m > 1)
160  // add the index of this walker to plus, duplicate m-1 times
161  {
162  plus.insert(plus.end(), m - 1, iw);
163  }
164  else if (m == 0)
165  // add the walker index to be killed/overwritten
166  {
167  minus.push_back(iw);
168  }
169  }
170  //save the number of local walkers to be removed. This will be collected later.
171  int nw_removed = minus.size();
172  //copy within the local node
173  int lower = std::min(plus.size(), minus.size());
174  while (lower > 0)
175  {
176  --lower;
177  int im = minus[lower]; //walker index to be replaced
178  int ip = plus[lower]; //walker index to be duplicated
179  W[im]->makeCopy(*(W[ip])); //copy the walker
180  W[im]->setParentID(W[ip]->getWalkerID());
181  W[im]->setWalkerID((++NumWalkersCreated) * num_contexts_ + MyContext);
182  minus.pop_back(); //remove it
183  plus.pop_back(); //remove it
184  }
185  std::fill(dN.begin(), dN.end(), 0);
186  //dN[ip] extra/missing walkers
187  if (plus.size())
188  {
189  dN[MyContext] = plus.size();
190  }
191  if (minus.size())
192  {
193  dN[MyContext] = -minus.size();
194  }
195  //dN[NumContexts] contains the number of surviving walkers
196  dN[num_contexts_] = icdiff;
197  //other data to compute survival rate and how many walkers are swapped
198  dN[num_contexts_ + 1] = nw_removed;
199  dN[num_contexts_ + 2] = plus.size();
200  dN[num_contexts_ + 3] = minus.size();
201  //collect the data
202  myComm->allreduce(dN);
203  //Each task will send or recv not both.
204  if (plus.size())
205  sendWalkers(W, plus);
206  if (minus.size())
207  recvWalkers(W, minus);
208  //app_log() << "RECONFIGURATION plus= " << dN[NumContexts+2] << " minus= " << dN[NumContexts+3] << std::endl;
209  //app_log() << "RECONFIGURATION ";
210  //for(int i=0; i<NumContexts; ++i) app_log() << dN[i] << " ";
211  //app_log() << std::endl;
212  //record the number of walkers created/destroyed
216  //collect surviving walkers
217  return dN[num_contexts_];
218 }
219 
220 void WalkerReconfigurationMPI::sendWalkers(MCWalkerConfiguration& W, const std::vector<IndexType>& plus)
221 {
222  std::vector<int> minusN, plusN;
223  for (int ip = 0; ip < num_contexts_; ip++)
224  {
225  if (dN[ip] > 0)
226  {
227  plusN.insert(plusN.end(), dN[ip], ip);
228  }
229  else if (dN[ip] < 0)
230  {
231  minusN.insert(minusN.end(), -dN[ip], ip);
232  }
233  }
234  int nswap = plusN.size();
235  int last = std::abs(dN[MyContext]) - 1;
236  int ic = 0;
237  while (ic < nswap && last >= 0)
238  {
239  if (plusN[ic] == MyContext)
240  {
241  int im = plus[last];
242  size_t byteSize = W[im]->byteSize();
243  W[im]->updateBuffer();
244  myComm->comm.send_n(W[im]->DataSet.data(), byteSize, minusN[ic]);
245  --last;
246  }
247  ++ic;
248  }
249 }
250 
251 void WalkerReconfigurationMPI::recvWalkers(MCWalkerConfiguration& W, const std::vector<IndexType>& minus)
252 {
253  std::vector<IndexType> minusN, plusN;
254  for (int ip = 0; ip < num_contexts_; ip++)
255  {
256  if (dN[ip] > 0)
257  {
258  plusN.insert(plusN.end(), dN[ip], ip);
259  }
260  else if (dN[ip] < 0)
261  {
262  minusN.insert(minusN.end(), -dN[ip], ip);
263  }
264  }
265  int nswap = plusN.size();
266  int last = std::abs(dN[MyContext]) - 1;
267  int ic = 0;
268  while (ic < nswap && last >= 0)
269  {
270  if (minusN[ic] == MyContext)
271  {
272  int im = minus[last];
273  size_t byteSize = W[im]->byteSize();
274  myComm->comm.receive_n(W[im]->DataSet.data(), byteSize, plusN[ic]);
275  W[im]->copyFromBuffer();
276  W[im]->setParentID(W[im]->getWalkerID());
277  W[im]->setWalkerID((++NumWalkersCreated) * num_contexts_ + MyContext);
278  --last;
279  }
280  ++ic;
281  }
282 }
283 } // namespace qmcplusplus
HamiltonianRef::FullPrecRealType FullPrecRealType
A set of walkers that are to be advanced by Metropolis Monte Carlo.
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
size_t getActiveWalkers() const
return the number of active walkers
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
void pop_back()
delete the last Walker_t*
FullPrecRealType UnitZeta
random number [0,1)
std::vector< int > ncopy_w
temporary storage for copy counters
#define Random
int LastWalker
ending index of the local walkers
FullPrecRealType DeltaStep
random number [0,1)/number of walkers
T min(T a, T b)
std::vector< FullPrecRealType > wConf
Wrapping information on parallelism.
Definition: Communicate.h:68
void allreduce(T &)
WalkerList_t::iterator iterator
FIX: a type alias of iterator for an object should not be for just one of many objects it holds...
A collection of functions for dividing fairly.
int FirstWalker
starting index of the local walkers
WalkerProperties::Indexes WP
Definition: ParticleSet.cpp:34
void recvWalkers(MCWalkerConfiguration &W, const std::vector< IndexType > &minus)
send the missing walkers from other node
Communicate * myComm
pointer to Communicate
Definition: MPIObjectBase.h:62
std::vector< IndexType > dN
the number of extra/missing walkers
void measureProperties(int iter)
take averages and writes to a file
std::vector< FullPrecRealType > curData
any temporary data includes many ridiculous conversions of integral types to and from fp ...
IndexType NumWalkersCreated
Number of walkers created by this rank.
IndexType num_contexts_
number of contexts
std::vector< FullPrecRealType > wOffset
WalkerReconfigurationMPI(Communicate *c=0)
default constructor
void sendWalkers(MCWalkerConfiguration &W, const std::vector< IndexType > &plus)
send the extra walkers to other node
Indexes
an enum denoting index of physical properties
Base class to control the walkers for DMC simulations.
void bcast(T &)
MCDataType< FullPrecRealType > EnsembleProperty
MCDataType< FullPrecRealType > ensemble_property_
ensemble properties
iterator end()
return the last iterator, [begin(), end())
Declare a global Random Number Generator.
IndexType SwapMode
0 is default
int branch(int iter, MCWalkerConfiguration &W, FullPrecRealType trigger) override
perform branch and swap walkers as required
int swapWalkers(MCWalkerConfiguration &W)
return the surviving Walkers
Declaration of QMCHamiltonian.
FullPrecRealType nwInv
1/(total number of walkers)
iterator begin()
return the first iterator