QMCPACK
qmcapp.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: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
9 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
10 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 // Ying Wai Li, yingwaili@ornl.gov, Oak Ridge National Laboratory
12 // Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
13 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
14 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
15 //
16 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
17 //////////////////////////////////////////////////////////////////////////////////////
18 
19 #include <stdexcept>
20 #include <memory>
21 #include "Configuration.h"
22 #include "Message/Communicate.h"
23 #include "Utilities/SimpleParser.h"
26 #include "OhmmsData/FileUtility.h"
27 #include "Host/sysutil.h"
28 #include "ProjectData.h"
29 #include "QMCApp/QMCMain.h"
30 #include "Utilities/qmc_common.h"
31 
32 #include <array>
33 
34 void output_hardware_info(Communicate* comm, Libxml2Document& doc, xmlNodePtr root);
35 
36 /** @file qmcapp.cpp
37  *@brief a main function for QMC simulation.
38  *
39  * @ingroup qmcapp
40  * @brief main function for qmcapp executable.
41  *
42  *Actual works are done by QMCAppBase and its derived classe.
43  *For other simulations, one can derive a class from QMCApps, similarly to MolecuApps.
44  */
45 int main(int argc, char** argv)
46 {
47  using namespace qmcplusplus;
48 #ifdef HAVE_MPI
49  mpi3::environment env(argc, argv);
50  OHMMS::Controller = new Communicate(env.world());
51 #endif
52  try
53  {
54  //qmc_common and MPI is initialized
56  int clones = 1;
57  std::vector<std::string> fgroup1, fgroup2;
58  int i = 1;
59  while (i < argc)
60  {
61  std::string c(argv[i]);
62  if (c[0] == '-')
63  {
64  if (c.find("clones") < c.size())
65  clones = atoi(argv[++i]);
66  if (c == "-debug")
68 
69  // Default setting is 'timer_level_coarse'
70  if (c.find("-enable-timers") < c.size())
71  {
72 #ifndef ENABLE_TIMERS
73  std::cerr
74  << "The '-enable-timers' command line option will have no effect. This executable was built without "
75  "ENABLE_TIMER set."
76  << std::endl;
77 #endif
78  int pos = c.find("=");
79  if (pos != std::string::npos)
80  {
81  std::string timer_level = c.substr(pos + 1);
82  getGlobalTimerManager().set_timer_threshold(timer_level);
83  }
84  }
85  if (c.find("-verbosity") < c.size())
86  {
87  int pos = c.find("=");
88  if (pos != std::string::npos)
89  {
90  std::string verbose_level = c.substr(pos + 1);
91  if (verbose_level == "low")
92  {
94  }
95  else if (verbose_level == "high")
96  {
98  }
99  else if (verbose_level == "debug")
100  {
102  }
103  else
104  {
105  std::cerr << "Unknown verbosity level: " << verbose_level << std::endl;
106  }
107  }
108  }
109  }
110  else
111  {
112  if (c.find("xml") < c.size())
113  fgroup1.push_back(argv[i]);
114  else
115  {
116  std::ifstream fin(argv[i], std::ifstream::in);
117  bool valid = !fin.fail();
118  while (valid)
119  {
120  std::vector<std::string> words;
121  getwords(words, fin);
122  if (words.size())
123  {
124  if (words[0].find("xml") < words[0].size())
125  {
126  int nc = 1;
127  if (words.size() > 1)
128  nc = atoi(words[1].c_str());
129  while (nc)
130  {
131  fgroup2.push_back(words[0]);
132  --nc;
133  }
134  }
135  }
136  else
137  valid = false;
138  }
139  }
140  }
141  ++i;
142  }
143  int in_files = fgroup1.size();
144  std::vector<std::string> inputs(in_files * clones + fgroup2.size());
145  copy(fgroup2.begin(), fgroup2.end(), inputs.begin());
146  i = fgroup2.size();
147  for (int k = 0; k < in_files; ++k)
148  for (int c = 0; c < clones; ++c)
149  inputs[i++] = fgroup1[k];
150  if (inputs.empty())
151  {
152  if (OHMMS::Controller->rank() == 0)
153  {
154  std::cerr << "No input file is given." << std::endl;
155  std::cerr << "Usage: qmcpack <input-files> " << std::endl;
156  }
158  return 1;
159  }
160  //safe to move on
161  Communicate* qmcComm = OHMMS::Controller;
162  if (inputs.size() > 1)
163  {
164  if (inputs.size() > OHMMS::Controller->size())
165  {
166  std::ostringstream msg;
167  msg << "main(). Current " << OHMMS::Controller->size() << " MPI ranks cannot accommodate all the "
168  << inputs.size() << " individual calculations in the ensemble. "
169  << "Increase the number of MPI ranks or reduce the number of calculations." << std::endl;
171  }
172  qmcComm = new Communicate(*OHMMS::Controller, inputs.size());
173  qmc_common.mpi_groups = inputs.size();
174  }
175  std::stringstream logname;
176  int inpnum = (inputs.size() > 1) ? qmcComm->getGroupID() : 0;
177  std::string myinput = inputs[qmcComm->getGroupID()];
178  myinput = myinput.substr(0, myinput.size() - 4);
179  logname << myinput;
180 
181  if (qmcComm->rank() != 0)
182  {
184  // might need to redirect debug stream to a file per rank if debugging is enabled
185  }
186  if (inputs.size() > 1 && qmcComm->rank() == 0)
187  {
188  std::array<char, 128> fn;
189  if (std::snprintf(fn.data(), fn.size(), "%s.g%03d.qmc", logname.str().c_str(), qmcComm->getGroupID()) < 0)
190  throw std::runtime_error("Error generating filename");
191  infoSummary.redirectToFile(fn.data());
194  }
195 
196  bool validInput = false;
197  app_log() << " Input file(s): ";
198  for (int k = 0; k < inputs.size(); ++k)
199  app_log() << inputs[k] << " ";
200  app_log() << std::endl;
201 
202  auto qmc = std::make_unique<QMCMain>(qmcComm);
203 
204  if (inputs.size() > 1)
205  validInput = qmc->parse(inputs[qmcComm->getGroupID()]);
206  else
207  validInput = qmc->parse(inputs[0]);
208 
209  if (!validInput)
210  qmcComm->barrier_and_abort("main(). Input invalid.");
211 
212  bool qmcSuccess = qmc->execute();
213  if (!qmcSuccess)
214  qmcComm->barrier_and_abort("main(). QMC Execution failed.");
215 
216  Libxml2Document timingDoc;
217  timingDoc.newDoc("resources");
218  output_hardware_info(qmcComm, timingDoc, timingDoc.getRoot());
219  getGlobalTimerManager().output_timing(qmcComm, timingDoc, timingDoc.getRoot());
220  qmc->getParticlePool().output_particleset_info(timingDoc, timingDoc.getRoot());
221  if (OHMMS::Controller->rank() == 0)
222  {
223  timingDoc.dump(qmc->getTitle() + ".info.xml");
224  }
225  getGlobalTimerManager().print(qmcComm);
226 
227  qmc.reset();
228  }
229  catch (const std::exception& e)
230  {
231  std::cerr << e.what() << std::endl;
232  APP_ABORT("Unhandled Exception");
233  }
234  catch (...)
235  {
236  APP_ABORT("Unhandled Exception (not derived from std::exception)");
237  }
238 
239  if (OHMMS::Controller->rank() == 0)
240  std::cout << std::endl << "QMCPACK execution completed successfully" << std::endl;
241 
243 
244  return 0;
245 }
246 
248 {
249  xmlNodePtr hardware = doc.addChild(root, "hardware");
250 
251  bool using_mpi = false;
252 #ifdef HAVE_MPI
253  using_mpi = true;
254  doc.addChild(hardware, "mpi_size", comm->size());
255 #endif
256  doc.addChild(hardware, "mpi", using_mpi);
257 
258  bool using_openmp = false;
259 #ifdef _OPENMP
260  using_openmp = true;
261  doc.addChild(hardware, "openmp_threads", omp_get_max_threads());
262 #endif
263  doc.addChild(hardware, "openmp", using_openmp);
264 }
class that handles xmlDoc
Definition: Libxml2Doc.h:76
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
int rank() const
return the rank
Definition: Communicate.h:116
Declaration of OutputManager class.
InfoStream infoSummary
std::ostream & app_log()
Definition: OutputManager.h:65
void shutOff()
Permanently shut off all streams.
void newDoc(const std::string &rootName)
Definition: Libxml2Doc.cpp:93
xmlNodePtr getRoot()
Definition: Libxml2Doc.h:88
int main(int argc, char **argv)
Definition: qmcapp.cpp:45
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
int size() const
return the number of tasks
Definition: Communicate.h:118
void redirectToFile(const std::string &fname)
Open a file and output to that file.
Definition: InfoStream.cpp:60
InfoStream infoLog
OutputManagerClass outputManager(Verbosity::HIGH)
void initialize(int argc, char **argv)
initialize options from the command-line
Definition: qmc_common.cpp:28
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
Wrapping information on parallelism.
Definition: Communicate.h:68
int getGroupID() const
return the group id
Definition: Communicate.h:121
omp_int_t omp_get_max_threads()
Definition: OpenMP.h:26
void output_hardware_info(Communicate *comm, Libxml2Document &doc, xmlNodePtr root)
Definition: qmcapp.cpp:247
declaration of ProgressReportEngine
Declaration of QMCMain class.
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
int mpi_groups
number of mpi groups
Definition: qmc_common.h:33
void finalize()
void redirectToSameStream(InfoStream &info)
Copy a stream.
Definition: InfoStream.cpp:70
void addChild(xmlNodePtr newnode)
Definition: Libxml2Doc.cpp:111
TimerManager< NewTimer > & getGlobalTimerManager()
InfoStream infoError
QMCState qmc_common
a unique QMCState during a run
Definition: qmc_common.cpp:111
void barrier_and_abort(const std::string &msg) const
int getwords(std::vector< std::string > &slist, std::istream &fp, std::string &aline)
void dump(const std::string &newxml)
Definition: Libxml2Doc.cpp:109
void setVerbosity(Verbosity level)