QMCPACK
SFNBranch.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) 2020 QMCPACK developers.
6 //
7 // File developed by: Peter Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
8 //
9 // File refactored from: SimpleFixedNodeBranch.cpp
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #include "SFNBranch.h"
14 #include <numeric>
15 #include "OhmmsData/FileUtility.h"
17 #include "Particle/Reptile.h"
20 
21 namespace qmcplusplus
22 {
24 
25 ///enum to yes/no options saved in sParam
26 enum
27 {
32 };
33 
34 SFNBranch::SFNBranch(RealType tau, RealType feedback, DMCRefEnergyScheme refenergy_update_scheme)
35  : WarmUpToDoSteps(0),
36  EtrialUpdateToDoSteps(0),
37  myNode(NULL),
38  ref_energy_collector(refenergy_update_scheme, std::max(1, static_cast<int>(1.0 / (feedback * tau))))
39 {
40  BranchMode.set(B_DMCSTAGE, 0); //warmup stage
41  BranchMode.set(B_POPCONTROL, 1); //use standard DMC
42  BranchMode.set(B_USETAUEFF, 1); //use taueff
43  BranchMode.set(B_CLEARHISTORY, 0); //clear history and start with the current average
44  BranchMode.set(B_KILLNODES, 0); //when killing walkers at nodes etrial is updated differently
45  vParam.fill(1.0);
46  vParam[SBVP::TAU] = tau;
47  vParam[SBVP::TAUEFF] = tau;
48  vParam[SBVP::FEEDBACK] = feedback;
51  R2Accepted(1.0e-10);
52  R2Proposed(1.0e-10);
53  //set the default values for integer parameters
54  iParam[B_WARMUPSTEPS] = 200;
58  iParam[B_COUNTER] = -1;
59  //default is no
60  sParam.resize(DUMMYOPT, "no");
61  //default is classic
62  branching_cutoff_scheme = "classic";
64 }
65 
66 SFNBranch::~SFNBranch() = default;
67 
69 {
70  m_param.add(iParam[B_WARMUPSTEPS], "warmupSteps");
71  m_param.add(iParam[B_WARMUPSTEPS], "warmupsteps");
72  m_param.add(iParam[B_ENERGYUPDATEINTERVAL], "energyUpdateInterval");
73  m_param.add(iParam[B_BRANCHINTERVAL], "branchInterval");
74  m_param.add(iParam[B_TARGETWALKERS], "targetWalkers");
75  m_param.add(iParam[B_TARGETWALKERS], "targetwalkers");
76  m_param.add(iParam[B_TARGETWALKERS], "target_walkers");
77  //trial energy
78  m_param.add(vParam[SBVP::EREF], "refEnergy");
79  m_param.add(vParam[SBVP::EREF], "ref_energy");
80  m_param.add(vParam[SBVP::EREF], "en_ref");
81  m_param.add(vParam[SBVP::TAU], "tau");
82  m_param.add(vParam[SBVP::TAU], "timestep");
83  m_param.add(vParam[SBVP::TAU], "timeStep");
84  m_param.add(vParam[SBVP::TAU], "TimeStep");
85  //filterscale: sets the filtercutoff to sigma*filterscale
86  m_param.add(vParam[SBVP::FILTERSCALE], "filterscale");
87  m_param.add(vParam[SBVP::SIGMA_BOUND], "sigmaBound");
88  //turn on/off effective tau onl for time-step error comparisons
89  m_param.add(sParam[USETAUOPT], "useBareTau");
90  m_param.add(sParam[MIXDMCOPT], "warmupByReconfiguration");
91  m_param.add(branching_cutoff_scheme, "branching_cutoff_scheme");
92 }
93 
94 int SFNBranch::initParam(const MCPopulation& population,
95  FullPrecRealType ene,
96  FullPrecRealType var,
97  bool fixW,
98  bool killwalker)
99 {
100  app_log() << " START ALL OVER " << std::endl;
101  BranchMode.set(B_POPCONTROL, !fixW); //fixW -> 0
102  BranchMode.set(B_KILLNODES, killwalker);
103 
104  BranchMode.set(B_DMC, 1); //set DMC
105  BranchMode.set(B_DMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup
106  vParam[SBVP::ETRIAL] = ene;
107  vParam[SBVP::EREF] = ene;
108  vParam[SBVP::SIGMA2] = var;
110  /// FIXME, magic number 50
112 
113  int nwtot_now = population.get_num_global_walkers();
114  if (iParam[B_TARGETWALKERS] == 0)
115  iParam[B_TARGETWALKERS] = nwtot_now;
116 
117  app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl;
118  app_log() << " time step = " << vParam[SBVP::TAU] << std::endl;
119  app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl;
120  app_log() << " trial energy = " << vParam[SBVP::ETRIAL] << std::endl;
121  app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl;
122  app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl;
123  app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl;
124  app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl;
125  app_log() << " branching cutoff scheme = " << branching_cutoff_scheme << std::endl;
126  app_log() << " branch cutoff, max = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX]
127  << std::endl;
128  app_log() << " QMC Status (BranchMode) = " << BranchMode << std::endl;
129 
130  return int(round(double(iParam[B_TARGETWALKERS]) / double(nwtot_now)));
131 }
132 
134 {
135  //target weight
136  const auto logN = std::log(static_cast<FullPrecRealType>(iParam[B_TARGETWALKERS]));
137  //population weight before branching
138  const FullPrecRealType pop_weight = wc_ensemble_prop.Weight;
139  //current energy
140  vParam[SBVP::ENOW] = wc_ensemble_prop.Energy;
141 
142  R2Accepted(wc_ensemble_prop.R2Accepted);
143  R2Proposed(wc_ensemble_prop.R2Proposed);
144  if (BranchMode[B_USETAUEFF])
146 
147  if (BranchMode[B_DMCSTAGE]) // main stage after warmup
148  {
149  if (WarmUpToDoSteps != 0)
150  throw UniformCommunicateError("Bug: WarmUpToDoSteps should be 0 after warmup.");
151 
152  // assuming ENOW only fluctuates around the mean (EREF) once warmup completes.
153  const auto ene = BranchMode[B_KILLNODES]
154  ? vParam[SBVP::ENOW] - std::log(wc_ensemble_prop.LivingFraction) / vParam[SBVP::TAUEFF]
155  : vParam[SBVP::ENOW];
156  ref_energy_collector.pushWeightEnergyVariance(wc_ensemble_prop.Weight, ene, wc_ensemble_prop.Variance);
157  // update the reference energy
158  auto [ene_avg, var_avg] = ref_energy_collector.getEnergyVariance();
159  vParam[SBVP::EREF] = ene_avg;
160 
161  // update Etrial based on EREF
163  {
165  if (EtrialUpdateToDoSteps == 0)
166  {
167  vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] + vParam[SBVP::FEEDBACK] * (logN - std::log(pop_weight));
169  }
170  }
171  else
172  {
173  throw UniformCommunicateError("Bug: FIXME SBVP::EREF should be calculated based on weights");
174  /// FIXME vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
175  }
176  }
177  else //warmup
178  {
179  if (WarmUpToDoSteps == 0)
180  throw UniformCommunicateError("Bug: WarmUpToDoSteps should be larger than 0 during warmup.");
181 
182  // Use Enow as the best estimate of ground state energy during warmup.
184  // update Etrial based on Enow as Enow is not yet converged in warmup stage
186  {
187  if (BranchMode[B_KILLNODES])
188  vParam[SBVP::ETRIAL] = (0.00 * vParam[SBVP::EREF] + 1.0 * vParam[SBVP::ENOW]) +
189  vParam[SBVP::FEEDBACK] * (logN - std::log(pop_weight)) -
190  std::log(wc_ensemble_prop.LivingFraction) / vParam[SBVP::TAU];
191  else
192  vParam[SBVP::ETRIAL] = vParam[SBVP::ENOW] + (logN - std::log(pop_weight)) / vParam[SBVP::TAU];
193  }
194  else
195  {
196  throw UniformCommunicateError("Bug: FIXME SBVP::EREF should be calculated based on weights");
197  /// FIXME vParam[SBVP::ETRIAL] = vParam[SBVP::ENOW];
198  }
199 
200  --WarmUpToDoSteps;
201  if (WarmUpToDoSteps == 0) //warmup is done
202  {
204  throw UniformCommunicateError("Bug: ref_energy_collector should not have been used during warmup.");
205 
206  vParam[SBVP::SIGMA2] = wc_ensemble_prop.Variance;
208  app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << std::endl;
209  if (BranchMode[B_USETAUEFF])
210  app_log() << "\n TauEff = " << vParam[SBVP::TAUEFF]
211  << "\n TauEff/Tau = " << vParam[SBVP::TAUEFF] / vParam[SBVP::TAU];
212  else
213  app_log() << "\n TauEff proposed = " << vParam[SBVP::TAUEFF] * R2Accepted.result() / R2Proposed.result();
214  app_log() << "\n Etrial = " << vParam[SBVP::ETRIAL] << std::endl;
215  app_log() << " Population average of energy = " << vParam[SBVP::ENOW] << std::endl;
216  app_log() << " Variance = " << vParam[SBVP::SIGMA2] << std::endl;
217  app_log() << "branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl;
218 
219  BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage
220  if (sParam[MIXDMCOPT] == "yes")
221  {
222  app_log() << "Switching to DMC with fluctuating populations" << std::endl;
223  BranchMode.set(B_POPCONTROL, 1); //use standard DMC
225  app_log() << " Etrial = " << vParam[SBVP::ETRIAL] << std::endl;
226  }
227  }
228  }
229 }
230 
232 {
233  std::ostringstream o;
234  //running RMC
235  if (BranchMode[B_RMC])
236  {
237  o << "====================================================";
238  o << "\n End of a RMC section";
239  o << "\n QMC counter = " << iParam[B_COUNTER];
240  o << "\n time step = " << vParam[SBVP::TAU];
241  o << "\n effective time step = " << vParam[SBVP::TAUEFF];
242  o << "\n reference energy = " << vParam[SBVP::EREF];
243  o << "\n reference variance = " << vParam[SBVP::SIGMA2];
244  o << "\n cutoff energy = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX];
245  o << "\n QMC Status (BranchMode) = " << BranchMode;
246  o << "\n====================================================";
247  }
248  else // running DMC
249  {
250  o << "====================================================";
251  o << "\n End of a DMC section";
252  o << "\n QMC counter = " << iParam[B_COUNTER];
253  o << "\n time step = " << vParam[SBVP::TAU];
254  o << "\n effective time step = " << vParam[SBVP::TAUEFF];
255  o << "\n trial energy = " << vParam[SBVP::ETRIAL];
256  o << "\n reference energy = " << vParam[SBVP::EREF];
257  o << "\n reference variance = " << vParam[SBVP::SIGMA2];
258  o << "\n target walkers = " << iParam[B_TARGETWALKERS];
259  o << "\n branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX];
260  o << "\n Feedback = " << vParam[SBVP::FEEDBACK];
261  o << "\n QMC Status (BranchMode) = " << BranchMode;
262  o << "\n====================================================";
263  }
264  app_log() << o.str() << std::endl;
265 }
266 
267 /** Parse the xml file for parameters
268  *@param cur current xmlNode
269  *
270  * Few important parameters are:
271  * <ul>
272  * <li> en_ref: a reference energy
273  * <li> num_gen: number of generations \f$N_G\f$ to reach equilibrium, used in the feedback parameter
274  * \f$ feed = \frac{1}{N_G \tau} \f$
275  * </ul>
276  */
277 bool SFNBranch::put(xmlNodePtr cur)
278 {
279  //save it
280  myNode = cur;
281  m_param.put(cur);
284  return true;
285 }
286 
288  FullPrecRealType targetSigma,
289  FullPrecRealType maxSigma,
290  int Nelec)
291 {
292  if (branching_cutoff_scheme == "DRV")
293  {
294  // eq.(3), J. Chem. Phys. 89, 3629 (1988).
295  // eq.(9), J. Chem. Phys. 99, 2865 (1993).
297  }
298  else if (branching_cutoff_scheme == "ZSGMA")
299  {
300  // eq.(6), Phys. Rev. B 93, 241118(R) (2016)
301  // do nothing if Nelec is not passed in.
302  if (Nelec > 0)
304  }
305  else if (branching_cutoff_scheme == "YL")
306  {
307  // a scheme from Ye Luo.
308  vParam[SBVP::BRANCHCUTOFF] = std::sqrt(variance) * std::min(targetSigma, std::sqrt(1.0 / vParam[SBVP::TAU]));
309  }
310  else if (branching_cutoff_scheme == "classic")
311  {
312  // default QMCPACK choice which is the same as v3.0.0 and before.
313  vParam[SBVP::BRANCHCUTOFF] = std::min(std::max(variance * targetSigma, maxSigma), 2.5 / vParam[SBVP::TAU]);
314  }
315  else
316  APP_ABORT("SFNBranch::setBranchCutoff unknown branching cutoff scheme " + branching_cutoff_scheme);
317 
320 }
321 
322 std::ostream& operator<<(std::ostream& os, SFNBranch::VParamType& rhs)
323 {
324  for (auto value : rhs)
325  os << std::setw(18) << std::setprecision(10) << value;
326  return os;
327 }
328 
329 } // namespace qmcplusplus
int initParam(const MCPopulation &population, FullPrecRealType ene, FullPrecRealType var, bool fixW, bool killwalker)
initialize branching parameters
Definition: SFNBranch.cpp:94
const ParticleSet & get_golden_electrons() const
Definition: MCPopulation.h:176
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
std::tuple< FullPrecReal, FullPrecReal > getEnergyVariance() const
return energy and variance
void printStatus() const
finalize the simulation
Definition: SFNBranch.cpp:231
void updateParamAfterPopControl(const MCDataType< FullPrecRealType > &wc_ensemble_prop, int Nelec)
perform branching
Definition: SFNBranch.cpp:133
T min(T a, T b)
1 for main, 0 for wamrup
Definition: SFNBranch.h:75
bool put(std::istream &is) override
read from std::istream
Definition: ParameterSet.h:42
int WarmUpToDoSteps
number of remaning steps in warmup, [0, iParam[B_WARMUPSTEPS]]
Definition: SFNBranch.h:306
BranchModeType BranchMode
Definition: SFNBranch.h:300
DMCRefEnergy ref_energy_collector
collect energy and variance history
Definition: SFNBranch.h:312
WalkerProperties::Indexes WP
Definition: ParticleSet.cpp:34
bool put(xmlNodePtr cur)
Parse the xml file for parameters.
Definition: SFNBranch.cpp:277
This a subclass for runtime errors that will occur on all ranks.
std::ostream & operator<<(std::ostream &out, const AntiSymTensor< T, D > &rhs)
controlling parameters of full precision real type
Definition: SFNBranch.h:145
xmlNodePtr myNode
save xml element
Definition: SFNBranch.h:310
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
accumulator_set< RealType > R2Accepted
a simple accumulator for energy
Definition: SFNBranch.h:314
SFNBranch(RealType tau, RealType feedback, DMCRefEnergyScheme)
Constructor.
Definition: SFNBranch.cpp:34
1 to clear the history
Definition: SFNBranch.h:81
void setBranchCutoff(FullPrecRealType variance, FullPrecRealType targetSigma, FullPrecRealType maxSigma, int Nelec=0)
set branch cutoff, max, filter
Definition: SFNBranch.cpp:287
1 for dmc, 0 for anything else
Definition: SFNBranch.h:73
ParameterSet m_param
set of parameters
Definition: SFNBranch.h:324
interval between branch, see population control
Definition: SFNBranch.h:106
MakeReturn< UnaryNode< FnLog, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t log(const Vector< T1, C1 > &l)
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>
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
return_type result() const
return the sum
Definition: accumulators.h:108
IndexType get_num_global_walkers() const
Definition: MCPopulation.h:168
DMCRefEnergyScheme
DMCRefEnergy schemes.
int EtrialUpdateToDoSteps
number of remaning steps in before adjusting ETRIAL, [0, iParam[B_ENERGYUPDATEINTERVAL]] ...
Definition: SFNBranch.h:308
Indexes
an enum denoting index of physical properties
1 for rmc, 0 for anything else
Definition: SFNBranch.h:87
counter for tracking object state
Definition: SFNBranch.h:104
QTFull::RealType FullPrecRealType
Definition: Configuration.h:66
1 to use taueff accordning to JCP 93, 0 to use tau
Definition: SFNBranch.h:79
warmup steps, valid when BranchMode[D_DMCSTAGE] == 0
Definition: SFNBranch.h:102
target total number of walkers per mpi group
Definition: SFNBranch.h:105
Declare a global Random Number Generator.
std::string branching_cutoff_scheme
scheme of branching cutoff
Definition: SFNBranch.h:322
void registerParameters()
create map between the parameter name and variables
Definition: SFNBranch.cpp:68
frequency of the trial energy updates, default 1
Definition: SFNBranch.h:103
accumulator_set< RealType > R2Proposed
a simple accumulator for energy
Definition: SFNBranch.h:316
1 to kill walkers when a node crossing is detected
Definition: SFNBranch.h:83
void pushWeightEnergyVariance(FullPrecReal weight, FullPrecReal ene, FullPrecReal var)
record weight, energy and variance.
size_t count() const
return record count.
1 for the standard dmc, 0 for the comb method
Definition: SFNBranch.h:77
std::vector< std::string > sParam
string parameters
Definition: SFNBranch.h:326