54 {
WC_send,
"WalkerControl::send"},
55 {
WC_recv,
"WalkerControl::recv"}};
60 use_fixed_pop_(use_fixed_pop),
65 num_ranks_(c->size()),
67 use_nonblocking_(true),
68 debug_disable_branching_(false),
70 saved_num_walkers_sent_(0)
83 hname.concat(
".dmc.dat");
86 dmcStream = std::make_unique<std::ofstream>(hname);
87 dmcStream->setf(std::ios::scientific, std::ios::floatfield);
89 (*dmcStream) <<
"# Index " << std::setw(20) <<
"LocalEnergy" << std::setw(20) <<
"Variance" << std::setw(20)
90 <<
"Weight" << std::setw(20) <<
"NumOfWalkers" << std::setw(20)
92 (*dmcStream) << std::setw(20) <<
"TrialEnergy" << std::setw(20) <<
"DiffEff";
93 (*dmcStream) << std::setw(20) <<
"LivingFraction";
94 (*dmcStream) << std::endl;
124 (*dmcStream) << std::setw(20) <<
trial_energy_ << std::setw(20)
140 do_not_branch =
true;
175 walker->Multiplicity = 1.0;
189 auto untouched_walkers =
walkers.size();
190 #if defined(HAVE_MPI) 199 swapWalkersSimple(pop);
210 const size_t good_walkers =
walkers.size();
211 for (
size_t iw = 0; iw < good_walkers; iw++)
213 size_t num_copies =
static_cast<int>(
walkers[iw]->Multiplicity);
214 while (num_copies > 1)
221 long save_id = walker_elements.
walker.getWalkerID();
222 walker_elements.walker = *
walkers[iw];
223 walker_elements.walker.setParentID(walker_elements.walker.getWalkerID());
224 walker_elements.walker.setWalkerID(save_id);
236 throw std::runtime_error(
"Potential bug! Population num_global_walkers mismatched!");
243 walker->Multiplicity = 1.0;
246 for (
int iw = 0; iw < untouched_walkers; iw++)
257 int num_good_walkers(0), num_total_copies(0);
260 const int num_copies =
static_cast<int>(
walker->Multiplicity);
261 num_good_walkers += num_copies > 0 ? 1 : 0;
262 num_total_copies += num_copies;
264 r2_accepted +=
walker->Properties(WP::R2ACCEPTED);
265 r2_proposed +=
walker->Properties(WP::R2PROPOSED);
269 e2sum += wgt *
e *
e;
295 std::vector<int>& fair_offset,
296 std::vector<int>& minus,
297 std::vector<int>& plus)
299 const int num_contexts = num_per_rank.size();
300 const int current_population = std::accumulate(num_per_rank.begin(), num_per_rank.end(), 0);
301 FairDivideLow(current_population, num_contexts, fair_offset);
302 for (
int ip = 0; ip < num_contexts; ip++)
304 int dn = num_per_rank[ip] - (fair_offset[ip + 1] - fair_offset[ip]);
306 plus.insert(plus.end(), dn, ip);
308 minus.insert(minus.end(), -dn, ip);
311 if (plus.size() != minus.size())
313 app_error() <<
"Walker send/recv pattern doesn't match. " 314 <<
"The send size " << plus.size() <<
" is not equal to the recv size " << minus.size() <<
" ." 316 throw std::runtime_error(
"Trying to swap in WalkerControl::swapWalkersSimple with mismatched queues");
321 #if defined(HAVE_MPI) 322 void WalkerControl::swapWalkersSimple(
MCPopulation& pop)
324 std::vector<int> minus, plus;
327 #ifdef MCWALKERSET_MPI_DEBUG 328 std::array<char, 128> fname;
329 if (std::snprintf(fname.data(), fname.size(),
"test.%d",
rank_num_) < 0)
330 throw std::runtime_error(
"Error generating filename");
331 std::ofstream fout(fname.data(), std::ios::app);
333 for (
int ic = 0; ic < plus.size(); ic++)
335 fout << plus[ic] <<
" ";
338 for (
int ic = 0; ic < minus.size(); ic++)
340 fout << minus[ic] <<
" ";
346 const int nswap = plus.size();
348 std::vector<std::pair<int, int>> ncopy_pairs;
349 for (
int iw = 0; iw < good_walkers.size(); iw++)
350 ncopy_pairs.push_back(std::make_pair(static_cast<int>(good_walkers[iw]->Multiplicity), iw));
351 std::sort(ncopy_pairs.begin(), ncopy_pairs.end());
357 job(
int wid,
int target_in) : walkerID(wid), target(target_in){};
361 std::vector<job> job_list;
362 std::vector<WalkerElementsRef> newW;
363 std::vector<int> ncopy_newW;
365 for (
int ic = 0; ic < nswap; ic++)
372 for (
int id = ic + 1;
id < nswap;
id++)
373 if (plus[ic] == plus[
id] && minus[ic] == minus[
id] && ncopy_pairs.back().first > 1)
375 ncopy_pairs.back().first--;
384 myComm->comm.send_value(nsentcopy, minus[ic]);
385 job_list.push_back(job(ncopy_pairs.back().second, minus[ic]));
386 #ifdef MCWALKERSET_MPI_DEBUG 387 fout <<
"rank " << plus[ic] <<
" sends a walker with " << nsentcopy <<
" copies to rank " << minus[ic]
395 if (ncopy_pairs.back().first > 1)
397 ncopy_pairs.back().first--;
398 std::sort(ncopy_pairs.begin(), ncopy_pairs.end());
402 good_walkers[ncopy_pairs.back().second]->Multiplicity = 0.0;
403 ncopy_pairs.pop_back();
412 myComm->comm.receive_n(&nsentcopy, 1, plus[ic]);
413 job_list.push_back(job(newW.size() - 1, plus[ic]));
414 if (plus[ic] != plus[ic + nsentcopy] || minus[ic] != minus[ic + nsentcopy])
415 throw std::runtime_error(
"WalkerControl::swapWalkersSimple send/recv pair checking failed!");
416 #ifdef MCWALKERSET_MPI_DEBUG 417 fout <<
"rank " << minus[ic] <<
" recvs a walker with " << nsentcopy <<
" copies from rank " << plus[ic]
421 ncopy_newW.push_back(nsentcopy);
430 std::vector<mpi3::request> requests;
432 for (
auto jobit = job_list.begin(); jobit != job_list.end(); jobit++)
433 good_walkers[jobit->walkerID]->SendInProgress =
false;
434 for (
auto jobit = job_list.begin(); jobit != job_list.end(); jobit++)
437 auto& awalker = good_walkers[jobit->walkerID];
438 size_t byteSize = awalker->byteSize();
439 if (!awalker->SendInProgress)
441 awalker->updateBuffer();
442 awalker->SendInProgress =
true;
445 requests.push_back(
myComm->comm.isend_n(awalker->DataSet.data(), byteSize, jobit->target));
449 myComm->comm.send_n(awalker->DataSet.data(), byteSize, jobit->target);
455 for (
int im = 0; im < requests.size(); im++)
465 std::vector<mpi3::request> requests;
466 for (
auto jobit = job_list.begin(); jobit != job_list.end(); jobit++)
469 auto& walker_elements = newW[jobit->walkerID];
470 auto& awalker = walker_elements.walker;
471 size_t byteSize = awalker.byteSize();
473 requests.push_back(
myComm->comm.ireceive_n(awalker.DataSet.data(), byteSize, jobit->target));
477 myComm->comm.receive_n(awalker.DataSet.data(), byteSize, jobit->target);
478 awalker.copyFromBuffer();
483 std::vector<bool> not_completed(requests.size(),
true);
484 bool completed =
false;
488 for (
int im = 0; im < requests.size(); im++)
489 if (not_completed[im])
491 if (requests[im].completed())
493 auto& walker_elements = newW[job_list[im].walkerID];
494 walker_elements.walker.copyFromBuffer();
495 not_completed[im] =
false;
509 for (
int iw = 0; iw < ncopy_pairs.size(); iw++)
510 good_walkers[ncopy_pairs[iw].
second]->Multiplicity = ncopy_pairs[iw].first;
512 for (
int iw = 0; iw < newW.size(); iw++)
513 newW[iw].
walker.Multiplicity = ncopy_newW[iw] + 1;
517 for (
int iw = 0; iw < good_walkers.size(); iw++)
518 TotalMultiplicity += good_walkers[iw]->Multiplicity;
520 throw std::runtime_error(
"Multiplicity check failed in WalkerControl::swapWalkersSimple!");
530 bad_walkers.reserve(
walkers.size());
532 if (static_cast<int>(
walker->Multiplicity) == 0)
533 bad_walkers.push_back(*
walker);
534 for (
MCPWalker& bad_walker : bad_walkers)
544 std::vector<IndexType> future_walkers(ncontexts, 0);
545 future_walkers[
comm->
rank()] = n_walkers;
547 return future_walkers;
552 int nw_target = 0, nw_max = 0;
555 params.
add(nw_target,
"targetwalkers");
556 params.
add(nw_max,
"max_walkers");
562 bool success = params.
put(cur);
564 catch (
const std::runtime_error& re)
571 app_log() <<
" WalkerControl parameters " << std::endl;
575 app_log() <<
" Max Walkers per MPI rank " <<
n_max_ << std::endl;
576 app_log() <<
" Min Walkers per MPI rank " <<
n_min_ << std::endl;
579 app_log() <<
" Disable branching for debugging as the user input request." << std::endl;
596 n_min_ = npernode / 5 + 1;
RandomBase< FullPrecRealType > & rng_
random number generator
IndexType saved_num_walkers_sent_
Number of walkers sent during the exchange.
std::filesystem::path dmcFname
filename for dmc.dat
void set_ensemble_property(const MCDataType< QMCTraits::FullPrecRealType > &ensemble_property)
WalkerElementsRef spawnWalker()
State Requirement:
Base class for any object which needs to know about a MPI communicator.
helper functions for EinsplineSetBuilder
int rank() const
return the rank
std::vector< int > fair_offset_
offset of the particle index for a fair distribution
std::vector< TimerIDName_t< T > > TimerNameList_t
UPtrVector< MCPWalker > & get_walkers()
FullPrecRealType trial_energy_
trial energy energy
std::ostream & app_error()
ScopeGuard< NewTimer > ScopedTimer
void writeDMCdat(int iter, const std::vector< FullPrecRealType > &curData)
take averages and writes to a file
std::vector< std::unique_ptr< T > > UPtrVector
const IndexType rank_num_
context id
bool debug_disable_branching_
disable branching for debugging
int size() const
return the number of tasks
void setMinMax(int nw_in, int nmax_in)
const IndexType num_ranks_
number of contexts
bool put(std::istream &is) override
read from std::istream
void branch(int iter, MCPopulation &pop, bool do_not_branch)
unified: perform branch and swap walkers as required
void FairDivideLow(int ntot, int npart, IV &adist)
partition ntot elements among npart
for(int i=0;i< size_test;++i) CHECK(Approx(gauss_random_vals[offset_for_rs+i])
IndexType n_min_
minimum number of walkers
bool use_nonblocking_
Use non-blocking isend/irecv.
void checkIntegrity() const
}@
Wrapping information on parallelism.
const std::string & getName() const
class to handle a set of parameters
WalkerProperties::Indexes WP
Communicate * myComm
pointer to Communicate
void syncWalkersPerRank(Communicate *comm)
IndexType n_max_
maximum number of walkers
static std::vector< IndexType > syncFutureWalkersPerRank(Communicate *comm, IndexType n_walkers)
void set_num_global_walkers(IndexType num_global_walkers)
static void killDeadWalkersOnRank(MCPopulation &pop)
kill dead walkers in the population
std::vector< int > num_per_rank_
number of walkers on each MPI rank after branching before load balancing
std::unique_ptr< T > UPtr
TimerList_t my_timers_
timers
void start()
start a block
Declaration of a TrialWaveFunction.
void add(PDT &aparam, const std::string &aname_in, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new parameter corresponding to an xmlNode <parameter>
std::vector< std::reference_wrapper< T > > RefVector
TimerNameList_t< WC_Timers > WalkerControlTimerNames
IndexType get_num_global_walkers() const
Indexes
an enum denoting index of physical properties
Walker< QMCTraits, PtclOnLatticeTraits > & walker
TimerManager< NewTimer > & getGlobalTimerManager()
void barrier_and_abort(const std::string &msg) const
~WalkerControl()
empty destructor to clean up the derived classes
IndexType max_copy_
maximum copy per walker
QMCTraits::IndexType IndexType
typedef of IndexType
IndexType get_num_local_walkers() const
WalkerControl(Communicate *c, RandomBase< FullPrecRealType > &rng, bool use_fixed_pop=false)
default constructor
MCDataType< FullPrecRealType > ensemble_property_
ensemble properties
void killWalker(MCPWalker &)
Kill a walker (just barely)
A container class to represent a walker.
void computeCurData(const UPtrVector< MCPWalker > &walkers, std::vector< FullPrecRealType > &curData)
compute curData
QMCTraits::FullPrecRealType FullPrecRealType
typedef of FullPrecRealType
std::unique_ptr< std::ofstream > dmcStream
file to save energy histogram
static void determineNewWalkerPopulation(const std::vector< int > &num_per_rank, std::vector< int > &fair_offset, std::vector< int > &minus, std::vector< int > &plus)
creates the distribution plan
bool use_fixed_pop_
if true, use fixed population
std::vector< FullPrecRealType > curData
any temporary data includes many ridiculous conversions of integral types to and from fp ...