QMCPACK
QMCDriverFactory.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) 2022 QMCPACK developers.
6 //
7 // File developed by: Bryan Clark, bclark@Princeton.edu, Princeton University
8 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
10 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
11 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
12 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
13 // Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
14 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
15 // Peter Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
16 //
17 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
18 //////////////////////////////////////////////////////////////////////////////////////
19 
20 
21 /**@file QMCDriverFactory.cpp
22  * @brief Implments QMCMain operators.
23  */
24 #include <queue>
25 
26 
28 #include "Utilities/qmc_common.h"
29 #include "QMCDriverFactory.h"
41 #include "OhmmsData/AttributeSet.h"
42 #include "OhmmsData/ParameterSet.h"
46 
47 namespace qmcplusplus
48 {
49 QMCDriverFactory::QMCDriverFactory(const ProjectData& project_data) : project_data_(project_data) {}
50 
51 /** Read the xml defining the driver for this QMC section
52  *
53  * Copy elision should result in just a move of the
54  * DriverAssemblyState
55  *
56  * Most (all) of this should be done by calling QMCDriverInput::readXML
57  * At some point in driver refactoring this should go there and
58  * QMCDriverInput created before the giant switch
59  */
61 {
63  std::string curName(castXMLCharToChar(cur->name));
64  std::string update_mode("pbyp");
65  std::string qmc_mode;
66  std::string multi_tag("no");
67  std::string warp_tag("no");
68  std::string append_tag("no");
69  std::string profiling_tag("no");
70  OhmmsAttributeSet aAttrib;
71  aAttrib.add(qmc_mode, "method",
72  {"", "vmc", "vmc_batch", "dmc", "dmc_batch", "csvmc", "rmc", "linear", "linear_batch", "wftest"});
73  aAttrib.add(update_mode, "move");
74  aAttrib.add(multi_tag, "multiple");
75  aAttrib.add(warp_tag, "warp");
76  aAttrib.add(append_tag, "append");
77  aAttrib.add(profiling_tag, "profiling");
78  aAttrib.add(das.traces_tag, "trace");
79  aAttrib.add(das.walkerlogs_tag, "walkerlog");
80  aAttrib.put(cur);
81  das.append_run = (append_tag == "yes");
82  das.enable_profiling = (profiling_tag == "yes");
83  das.what_to_do[SPACEWARP_MODE] = (warp_tag == "yes");
84  das.what_to_do[MULTIPLE_MODE] = (multi_tag == "yes");
85  das.what_to_do[UPDATE_MODE] = (update_mode == "pbyp");
87  infoLog.flush();
88 
89  // Really by position if you don't write <qmc name="xxx",,,>
90  // you can write <vmc ...> so hacky
91  if (curName != "qmc")
92  qmc_mode = curName;
93 
94  const int nchars = qmc_mode.size();
95 
96  using DV = ProjectData::DriverVersion;
98  {
99  case DV::BATCH:
100  if (qmc_mode.find("vmc") < nchars) // order matters here
102  else if (qmc_mode.find("dmc") < nchars) // order matters here
104  else if (qmc_mode.find("linear") < nchars)
106  else
107  throw UniformCommunicateError("QMC mode unknown. Valid modes for batched drivers are : vmc, dmc, linear.");
108  break;
109  // Begin to separate driver version = batch input reading from the legacy input parsing
110  case DV::LEGACY:
111  if (qmc_mode.find("linear_batch") < nchars) // order matters here
113  else if (qmc_mode.find("linear") < nchars)
115  else
116  {
117  if (qmc_mode.find("ptcl") < nchars)
118  das.what_to_do[UPDATE_MODE] = 1;
119  if (qmc_mode.find("mul") < nchars)
120  das.what_to_do[MULTIPLE_MODE] = 1;
121  if (qmc_mode.find("warp") < nchars)
122  das.what_to_do[SPACEWARP_MODE] = 1;
123  if (qmc_mode.find("rmc") < nchars)
125  else if (qmc_mode.find("vmc_batch") < nchars) // order matters here
127  else if (qmc_mode.find("vmc") < nchars)
129  else if (qmc_mode.find("dmc_batch") < nchars) // order matters here
131  else if (qmc_mode.find("dmc") < nchars)
133  else if (qmc_mode == "wftest")
135  else
136  throw std::runtime_error("qmc method cannot be empty!");
137  }
138  }
139  return das;
140 }
141 
142 std::unique_ptr<QMCDriverInterface> QMCDriverFactory::createQMCDriver(xmlNodePtr cur,
143  DriverAssemblyState& das,
144  const std::optional<EstimatorManagerInput>& emi,
145  MCWalkerConfiguration& qmc_system,
149  Communicate* comm) const
150 {
151  ///////////////////////////////////////////////
152  // get primaryPsi and primaryH
153  ///////////////////////////////////////////////
154  TrialWaveFunction* primaryPsi = 0;
155  QMCHamiltonian* primaryH = 0;
156  std::queue<TrialWaveFunction*> targetPsi; //FIFO
157  std::queue<QMCHamiltonian*> targetH; //FIFO
158  xmlNodePtr tcur = cur->children;
159  std::unique_ptr<QMCDriverInterface> new_driver;
160  while (tcur != NULL)
161  {
162  if (xmlStrEqual(tcur->name, (const xmlChar*)"qmcsystem"))
163  {
164  const std::string wf_name(getXMLAttributeValue(tcur, "wavefunction"));
165  if (!wf_name.empty())
166  {
167  targetPsi.push(wavefunction_pool.getWaveFunction(wf_name));
168  }
169  else
170  {
171  app_warning() << " qmcsystem does not have wavefunction. Assign 0" << std::endl;
172  targetPsi.push(0);
173  }
174  const std::string ham_name(getXMLAttributeValue(tcur, "hamiltonian"));
175  if (!ham_name.empty())
176  {
177  targetH.push(hamiltonian_pool.getHamiltonian(ham_name));
178  }
179  else
180  {
181  app_warning() << " qmcsystem does not have hamiltonian. Assign 0" << std::endl;
182  targetH.push(0);
183  }
184  }
185  tcur = tcur->next;
186  }
187  //mark the first targetPsi and targetH as the primaries
188  if (targetH.empty())
189  {
190  primaryPsi = wavefunction_pool.getPrimary();
191  primaryH = hamiltonian_pool.getPrimary();
192  }
193  else
194  {
195  primaryPsi = targetPsi.front();
196  // targetPsi.pop();
197  primaryH = targetH.front();
198  // targetH.pop();
199  }
200  //set primaryH->Primary
201  primaryH->setPrimary(true);
202 
203  ////flux is evaluated only with single-configuration VMC
204  //if(curRunType ==QMCRunType::VMC && !curQmcModeBits[MULTIPLE_MODE])
205  //{
206  // OperatorBase* flux=primaryH->getHamiltonian("Flux");
207  // if(flux == 0) primaryH->addOperator(new ConservedEnergy,"Flux");
208  //}
209  //else
210  //{
211  // primaryH->remove("Flux");
212  //}
213  //(SPACEWARP_MODE,MULTIPE_MODE,UPDATE_MODE)
214  if (das.new_run_type == QMCRunType::VMC || das.new_run_type == QMCRunType::CSVMC)
215  {
216  //VMCFactory fac(curQmcModeBits[UPDATE_MODE],cur);
217  VMCFactory fac(das.what_to_do.to_ulong(), cur);
218  new_driver = fac.create(project_data_, qmc_system, *primaryPsi, *primaryH, comm, das.enable_profiling);
219  //TESTING CLONE
220  //TrialWaveFunction* psiclone=primaryPsi->makeClone(qmc_system);
221  //qmcDriver = fac.create(qmc_system,*psiclone,*primaryH,particle_pool,hamiltonian_pool);
222  }
223  else if (das.new_run_type == QMCRunType::VMC_BATCH)
224  {
225  VMCFactoryNew fac(cur, das.what_to_do[UPDATE_MODE]);
226  new_driver = fac.create(project_data_, emi, qmc_system,
227  MCPopulation(comm->size(), comm->rank(), &qmc_system, primaryPsi, primaryH),
228  qmc_system.getSampleStack(), comm);
229  }
230  else if (das.new_run_type == QMCRunType::DMC)
231  {
232  DMCFactory fac(das.what_to_do[UPDATE_MODE], das.what_to_do[GPU_MODE], cur);
233  new_driver = fac.create(project_data_, qmc_system, *primaryPsi, *primaryH, comm, das.enable_profiling);
234  }
235  else if (das.new_run_type == QMCRunType::DMC_BATCH)
236  {
237  DMCFactoryNew fac(cur, das.what_to_do[UPDATE_MODE]);
238  new_driver = fac.create(project_data_, emi, qmc_system,
239  MCPopulation(comm->size(), comm->rank(), &qmc_system, primaryPsi, primaryH), comm);
240  }
241  else if (das.new_run_type == QMCRunType::RMC)
242  {
243  RMCFactory fac(das.what_to_do[UPDATE_MODE], cur);
244  new_driver = fac.create(project_data_, qmc_system, *primaryPsi, *primaryH, comm);
245  }
246  else if (das.new_run_type == QMCRunType::LINEAR_OPTIMIZE)
247  {
248 #ifdef MIXED_PRECISION
249  APP_ABORT("QMCDriverFactory::createQMCDriver : method=\"linear\" is not safe with CPU mixed precision. Please use "
250  "full precision build instead.");
251 #endif
253  new QMCFixedSampleLinearOptimize(project_data_, qmc_system, *primaryPsi, *primaryH, comm);
254  //ZeroVarianceOptimize *opt = new ZeroVarianceOptimize(qmc_system,*primaryPsi,*primaryH );
255  opt->setWaveFunctionNode(wavefunction_pool.getWaveFunctionNode("psi0"));
256  new_driver.reset(opt);
257  }
258  else if (das.new_run_type == QMCRunType::LINEAR_OPTIMIZE_BATCH)
259  {
260 #ifdef MIXED_PRECISION
261  APP_ABORT("QMCDriverFactory::createQMCDriver : method=\"linear_batch\" is not safe with CPU mixed precision. "
262  "Please use full precision build instead.");
263 #endif
264  auto opt = QMCWFOptLinearFactoryNew(cur, project_data_, emi, qmc_system,
265  MCPopulation(comm->size(), comm->rank(), &qmc_system, primaryPsi, primaryH),
266  qmc_system.getSampleStack(), comm);
267  opt->setWaveFunctionNode(wavefunction_pool.getWaveFunctionNode("psi0"));
268  new_driver = std::move(opt);
269  }
270  else if (das.new_run_type == QMCRunType::WF_TEST)
271  {
272  app_log() << "Testing wavefunctions." << std::endl;
273  QMCDriverInterface* temp_ptr =
274  new WaveFunctionTester(project_data_, qmc_system, *primaryPsi, *primaryH, particle_pool, comm);
275  new_driver.reset(temp_ptr);
276  }
277  else
278  {
279  APP_ABORT("Unhandled run type: " << static_cast<int>(das.new_run_type));
280  }
281  if (das.what_to_do[MULTIPLE_MODE])
282  {
283  while (targetH.size())
284  {
285  new_driver->add_H_and_Psi(targetH.front(), targetPsi.front());
286  targetH.pop();
287  targetPsi.pop();
288  }
289  }
290 
291  infoSummary.flush();
292  infoLog.flush();
293  //add trace information
294  bool allow_traces = das.traces_tag == "yes" ||
295  (das.traces_tag == "none" && (das.new_run_type == QMCRunType::VMC || das.new_run_type == QMCRunType::DMC));
296  new_driver->requestTraces(allow_traces);
297 
298  //add trace information
299  bool allow_walker_logs = das.walkerlogs_tag == "yes" ||
300  (das.walkerlogs_tag == "none" && (das.new_run_type == QMCRunType::VMC || das.new_run_type == QMCRunType::DMC || das.new_run_type == QMCRunType::VMC_BATCH || das.new_run_type == QMCRunType::DMC_BATCH));
301  new_driver->requestWalkerLogs(allow_walker_logs);
302 
303  return new_driver;
304 }
305 } // namespace qmcplusplus
DMC type: dmc, dmc-ptcl.
std::unique_ptr< QMCDriver > create(const ProjectData &project_data, MCWalkerConfiguration &w, TrialWaveFunction &psi, QMCHamiltonian &h, Communicate *comm, bool enable_profiling)
Definition: DMCFactory.cpp:24
QMCDriverFactory(const ProjectData &project_data)
Application uses this constructor param[in] project_data this is stored as a reference and this state...
std::unique_ptr< QMCFixedSampleLinearOptimizeBatched > QMCWFOptLinearFactoryNew(xmlNodePtr cur, const ProjectData &project_data, const std::optional< EstimatorManagerInput > &global_emi, WalkerConfigurations &wc, MCPopulation &&pop, SampleStack &samples, Communicate *comm)
A set of walkers that are to be advanced by Metropolis Monte Carlo.
std::ostream & app_warning()
Definition: OutputManager.h:69
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
DriverAssemblyState readSection(xmlNodePtr cur) const
default constructor
InfoStream infoSummary
std::unique_ptr< QMCDriverInterface > create(const ProjectData &project_data, const std::optional< EstimatorManagerInput > &global_emi, WalkerConfigurations &wc, MCPopulation &&pop, SampleStack &samples, Communicate *comm)
create a VMCBatched driver.
bit for space-warping
Definition: DriverTraits.h:30
bit for move: walker or pbyp
Definition: DriverTraits.h:28
std::ostream & app_log()
Definition: OutputManager.h:65
if(c->rank()==0)
class ProjectData
Definition: ProjectData.h:36
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
bit to use GPU driver
Definition: DriverTraits.h:32
Collection of Local Energy Operators.
EstimatorManagerInput emi(estimators_doc.getRoot())
int size() const
return the number of tasks
Definition: Communicate.h:118
InfoStream infoLog
Creates a common base class pointer for QMCDriver and QMCDriverNew to share.
std::unique_ptr< QMCDriverInterface > create(const ProjectData &project_data, const std::optional< EstimatorManagerInput > global_emi, WalkerConfigurations &wc, MCPopulation &&pop, Communicate *comm)
create a DMCBatched driver.
Wrapping information on parallelism.
Definition: Communicate.h:68
DriverVersion getDriverVersion() const noexcept
DriverVersion
Enum for global scope switch of design from legacy driver based to batch driver based.
Definition: ProjectData.h:43
Compilation units that construct QMCDriverInput need visibility to the actual input classes types in ...
Test the correctness of TrialWaveFunction for the values, gradients and laplacians.
const ProjectData & project_data_
project info for accessing global fileroot and series id
Declaration of WaveFunctionPool.
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
bit for multple configuration
Definition: DriverTraits.h:29
This a subclass for runtime errors that will occur on all ranks.
Manage a collection of ParticleSet objects.
Definition of QMCDriver which performs VMC and optimization.
char * castXMLCharToChar(xmlChar *c)
assign a value from a node. Use specialization for classes.
Definition: libxmldefs.h:62
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
std::string getXMLAttributeValue(const xmlNodePtr cur, const std::string_view name)
get the value string for attribute name if name is unfound in cur you get an empty string back this i...
std::unique_ptr< QMCDriver > create(const ProjectData &project_data, MCWalkerConfiguration &w, TrialWaveFunction &psi, QMCHamiltonian &h, Communicate *comm)
Definition: RMCFactory.cpp:20
RMC type: rmc, rmc-ptcl.
Declaration of a TrialWaveFunction.
std::unique_ptr< QMCDriverInterface > create(const ProjectData &project_data, MCWalkerConfiguration &w, TrialWaveFunction &psi, QMCHamiltonian &h, Communicate *comm, bool enable_profiling)
Definition: VMCFactory.cpp:33
Declaration of HamiltonianPool.
void flush()
flush stream buffer
Definition: InfoStream.cpp:39
Class to represent a many-body trial wave function.
const SampleStack & getSampleStack() const
Definition of QMCDriver which performs VMC and optimization.
Implements wave-function optimization.
VMC type: vmc, vmc-ptcl, vmc-multiple, vmc-ptcl-multiple.
void setPrimary(bool primary)
set PRIMARY bit of all the components
void add(PDT &aparam, const std::string &aname, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new attribute
Definition: AttributeSet.h:42
Manage a collection of TrialWaveFunction objects.
Manage a collection of QMCHamiltonian objects.