OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Main.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
3 //
4 // All rights reserved
5 //
6 // This file is part of OPAL.
7 //
8 // OPAL is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
15 //
16 #include "opal.h"
17 
18 #include "H5hut.h"
19 
22 #include "OpalParser/OpalParser.h"
23 #include "Parser/FileStream.h"
24 #include "Parser/TerminalStream.h"
25 #include "Utilities/Timer.h"
26 #include "Fields/Fieldmap.h"
27 #include "FixedAlgebra/FTps.h"
28 
29 #include "BasicActions/Option.h"
30 #include "Utilities/Options.h"
33 #include "Utilities/Util.h"
34 
36 
37 #include "OPALconfig.h"
38 
39 #ifdef ENABLE_AMR
40 #include <AMReX_ParallelDescriptor.H>
41 #endif
42 
43 // IPPL
44 #include "Message/Communicate.h"
45 #include "Utility/Inform.h"
46 #include "Utility/IpplException.h"
47 #include "Utility/IpplInfo.h"
48 #include "Utility/IpplTimings.h"
49 #include "GSLErrorHandling.h"
50 
51 #include <gsl/gsl_errno.h>
52 
53 #include <boost/filesystem.hpp>
54 #include <boost/system/error_code.hpp>
55 
56 #include <cstring>
57 #include <iomanip>
58 #include <iostream>
59 #include <set>
60 
63 
64 namespace {
65  void printStdoutHeader() {
66  OPALTimer::Timer simtimer;
67  std::string dateStr(simtimer.date());
68  std::string timeStr(simtimer.time());
69  std::string mySpace(" ");
70 
71  *gmsg << mySpace << " ____ _____ ___ " << endl;
72  *gmsg << mySpace << " / __ \\| __ \\ /\\ | | " << endl;
73  *gmsg << mySpace << " | | | | |__) / \\ | |" << endl;
74  *gmsg << mySpace << " | | | | ___/ /\\ \\ | |" << endl ;
75  *gmsg << mySpace << " | |__| | | / ____ \\| |____" << endl;
76  *gmsg << mySpace << " \\____/|_| /_/ \\_\\______|" << endl;
77 
78  std::string gitRevision = "git rev. " + Util::getGitRevision();
79  std::string copyRight = "(c) PSI, http://amas.web.psi.ch";
80  *gmsg << endl
81  << "This is OPAL (Object Oriented Parallel Accelerator Library) Version " << OPAL_PROJECT_VERSION << "\n"
82  << std::setw(37 + gitRevision.length() / 2) << std::right << gitRevision << "\n\n" << endl
83  << std::setw(37 + copyRight.length() / 2) << std::right << copyRight << "\n\n" << endl
84  << "The optimiser (former opt-Pilot) is integrated " << endl
85  << endl;
86 
87  *gmsg << "Please send cookies, goodies or other motivations (wine and beer ... ) \nto the OPAL developers " << PACKAGE_BUGREPORT << "\n" << endl;
88  *gmsg << "Time: " << timeStr << " date: " << dateStr << "\n" << endl;
89  }
90 
91  void printHelp() {
92  printStdoutHeader();
93 
94  INFOMSG("\n");
95  INFOMSG("Usage: opal [<option> <option> ...]\n");
96  INFOMSG(" The possible values for <option> are:\n");
97  INFOMSG(" --version : Print the version of opal.\n");
98  INFOMSG(" --version-full : Print the version of opal with additional informations.\n");
99  INFOMSG(" --git-revision : Print the revision hash of the repository.\n");
100  INFOMSG(" --input <fname> : Specifies the input file <fname>.\n");
101  INFOMSG(" --restart <n> : Performes a restart from step <n>.\n");
102  INFOMSG(" --restartfn <fname> : Uses the file <fname> to restart from.\n");
103 #ifdef ENABLE_AMR
104  INFOMSG(" --noInitAMR : Disable initialization of AMR\n");
105 #endif
106  Ippl::printHelp();
107  INFOMSG(" --help : Display this command-line summary.\n");
108  INFOMSG(endl);
109  }
110 }
111 
112 
113 bool checkInitAmrFlag(int argc, char* argv[]) {
114  std::string noamr = "noInitAMR";
115  bool initAMR = true;
116  for (int i = 0; i < argc; ++i) {
117  std::string sargv = std::string(argv[i]);
118  if ( sargv.find(noamr) != std::string::npos ) {
119  initAMR = false;
120  break;
121  }
122  }
123  return initAMR;
124 }
125 
126 
127 int main(int argc, char *argv[]) {
128  Ippl *ippl = new Ippl(argc, argv);
129  gmsg = new Inform("OPAL");
130 
131  namespace fs = boost::filesystem;
132 
133 #ifdef ENABLE_AMR
134  bool initAMR = checkInitAmrFlag(argc, argv);
135  if ( initAMR ) {
136  // false: build no parmparse, we use the OPAL parser instead.
137  amrex::Initialize(argc, argv, false, Ippl::getComm());
138  }
139 #endif
140 
141  H5SetVerbosityLevel(1); //65535);
142 
143  gsl_set_error_handler(&handleGSLErrors);
144 
145  static IpplTimings::TimerRef mainTimer = IpplTimings::getTimer("mainTimer");
146  IpplTimings::startTimer(mainTimer);
147 
148 
149  if(Ippl::myNode() == 0) remove("errormsg.txt");
150 
151  const OpalParser parser;
152 
153  std::cout.precision(16);
154  std::cout.setf(std::ios::scientific, std::ios::floatfield);
155  std::cerr.precision(16);
156  std::cerr.setf(std::ios::scientific, std::ios::floatfield);
157 
158  // Set global truncation orders.
162 
164 
165  /*
166  Make a directory data for some of the output
167  */
168  if(Ippl::myNode() == 0) {
169  if (!fs::exists(opal->getAuxiliaryOutputDirectory())) {
170  boost::system::error_code error_code;
171  if (!fs::create_directory(opal->getAuxiliaryOutputDirectory(), error_code)) {
172  std::cerr << error_code.message() << std::endl;
173  // use error code to prevent create_directory from throwing an exception
174  }
175  }
176  }
177  Ippl::Comm->barrier();
178  if (!fs::is_directory(opal->getAuxiliaryOutputDirectory())) {
179  std::cerr << "unable to create directory; aborting" << std::endl;
180  abort();
181  }
182 
183  opal->storeArguments(argc, argv);
184  try {
186 
187  // Read startup file.
189 
190  char *startup = getenv("HOME");
191  boost::filesystem::path p = strncat(startup, "/init.opal", 20);
192  if (startup != NULL && is_regular_file(p)) {
193 
194  FileStream::setEcho(false);
195  FileStream *is;
196 
197  try {
198  is = new FileStream(startup);
199  } catch(...) {
200  is = 0;
201  ERRORMSG("Could not open startup file \"" << startup << "\".\n"
202  << "Note: this is not mandatory for an OPAL simulation!\n");
203  }
204 
205  if(is) {
206  *gmsg << "Reading startup file \"" << startup << "\"." << endl;
207  parser.run(is);
208  *gmsg << "Finished reading startup file." << endl;
209  }
211  } else {
212  *gmsg << level5
213  << "Couldn't find startup file \"" << startup << "\".\n"
214  << "Note: this is not mandatory for an OPAL simulation!\n" << endl;
215  }
216 
217  if(argc <= 1) {
218  // Run commands from standard input
219  parser.run(new TerminalStream("OPAL"));
220  } else {
221  int inputFileArgument = -1;
222  std::string fname;
223  std::string restartFileName;
224  // // will write dumping date into a new h5 file
225  for(int ii = 1; ii < argc; ++ ii) {
226  std::string argStr = std::string(argv[ii]);
227  // The sequence of the two arguments is free
228  if (argStr == std::string("-h") ||
229  argStr == std::string("-help") ||
230  argStr == std::string("--help")) {
231  ::printHelp();
232  exit(0);
233  } else if (argStr == std::string("--version")) {
234  if (Ippl::myNode() == 0) {
235  std::cout << OPAL_PROJECT_VERSION << std::endl;
236  }
237  exit(0);
238  } else if (argStr == std::string("--version-full")) {
239  ::printStdoutHeader();
240  INFOMSG("OPAL Version " << OPAL_PROJECT_VERSION << ", git rev. " << Util::getGitRevision() << endl);
242  std::string options = (IpplInfo::compileOptions() +
243  std::string(" ") +
244  std::string(OPAL_COMPILE_OPTIONS) +
245  std::string(" "));
246  std::set<std::string> uniqOptions;
247  while (options.length() > 0) {
248  size_t n = options.find_first_of(' ');
249  while (n == 0) {
250  options = options.substr(n + 1);
251  n = options.find_first_of(' ');
252  }
253 
254  uniqOptions.insert(options.substr(0, n));
255  options = options.substr(n + 1);
256  }
257  for (auto it: uniqOptions) {
258  options += it + " ";
259  }
260 
261  std::string header("Compile-time options: ");
262  while (options.length() > 58) {
263  std::string line = options.substr(0, 58);
264  size_t n = line.find_last_of(' ');
265  INFOMSG(header << line.substr(0, n) << "\n");
266 
267  header = std::string(22, ' ');
268  options = options.substr(n + 1);
269  }
270  INFOMSG(header << options << endl);
271  exit(0);
272  } else if (argStr == std::string("--git-revision")) {
273  if (Ippl::myNode() == 0) {
274  std::cout << Util::getGitRevision() << std::endl;
275  }
276  exit(0);
277  } else if (argStr == std::string("--input")) {
278  ++ ii;
279  inputFileArgument = ii;
280  continue;
281  } else if (argStr == std::string("-restart") ||
282  argStr == std::string("--restart")) {
283  opal->setRestartRun();
284  opal->setRestartStep(atoi(argv[++ ii]));
285  continue;
286  } else if (argStr == std::string("-restartfn") ||
287  argStr == std::string("--restartfn")) {
288  restartFileName = std::string(argv[++ ii]);
289  continue;
290  } else if ( argStr.find("noInitAMR") != std::string::npos) {
291  // do nothing here
292  } else {
293  if (inputFileArgument == -1 &&
294  (ii == 1 || ii + 1 == argc) &&
295  argv[ii][0] != '-') {
296  inputFileArgument = ii;
297  continue;
298  } else {
299  INFOMSG("Unknown argument \"" << argStr << "\"" << endl);
300  ::printHelp();
301  exit(1);
302  }
303  }
304  }
305 
306  ::printStdoutHeader();
307  if (inputFileArgument == -1) {
308  INFOMSG("No input file provided!" << endl);
309  exit(1);
310  }
311 
312  fname = std::string(argv[inputFileArgument]);
313  if (!fs::exists(fname)) {
314  INFOMSG("Input file \"" << fname << "\" doesn't exist!" << endl);
315  exit(1);
316  }
317 
318  opal->storeInputFn(fname);
319 
320  if (opal->inRestartRun()) {
321  if (restartFileName == "")
322  restartFileName = opal->getInputBasename() + std::string(".h5");
323  if (!fs::exists(restartFileName)) {
324  INFOMSG("Restart file \"" << restartFileName << "\" doesn't exist!" << endl);
325  exit(1);
326  }
327  opal->setRestartFileName(restartFileName);
328  }
329 
330  FileStream *is;
331 
332  try {
333  is = new FileStream(fname);
334  } catch(...) {
335  is = 0;
336  *gmsg << "Input file \"" << fname << "\" not found." << endl;
337  }
338 
339  if(is) {
340  *gmsg << "* Reading input stream \"" << fname << "\"." << endl;
341  parser.run(is);
342  *gmsg << "* End of input stream \"" << fname << "\"." << endl;
343  }
344  }
345 
346  if(Ippl::myNode() == 0) {
347  std::ifstream errormsg("errormsg.txt");
348  if(errormsg.good()) {
349  char buffer[256];
350  std::string closure(" *\n");
351  ERRORMSG("\n"
352  << "* **********************************************************************************\n"
353  << "* ************** W A R N I N G / E R R O R * * M E S S A G E S *********************\n"
354  << "* **********************************************************************************"
355  << endl);
356  errormsg.getline(buffer, 256);
357  while(errormsg.good()) {
358  ERRORMSG("* ");
359  if(errormsg.gcount() == 1) {
360  ERRORMSG(closure);
361  } else if ((size_t)errormsg.gcount() <= closure.size()) {
362  ERRORMSG(buffer << closure.substr(errormsg.gcount() - 1));
363  } else {
364  ERRORMSG(buffer << endl);
365  }
366  errormsg.getline(buffer, 256);
367  }
368  ERRORMSG("* " << closure
369  << "* **********************************************************************************\n"
370  << "* **********************************************************************************"
371  << endl);
372  }
373  errormsg.close();
374  }
375 
376  } catch(EarlyLeaveException& ex) {
377  // do nothing here
378  } catch(OpalException &ex) {
379  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
380  errorMsg << "\n*** User error detected by function \""
381  << ex.where() << "\"\n";
382  // stat->printWhere(errorMsg, true);
383  std::string what = ex.what();
384  size_t pos = what.find_first_of('\n');
385  do {
386  errorMsg << " " << what.substr(0, pos) << endl;
387  what = what.substr(pos + 1, std::string::npos);
388  pos = what.find_first_of('\n');
389  } while (pos != std::string::npos);
390  errorMsg << " " << what << endl;
391 
392  MPI_Abort(MPI_COMM_WORLD, -100);
393  } catch(ClassicException &ex) {
394  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
395  errorMsg << "\n*** User error detected by function \""
396  << ex.where() << "\"\n";
397  // stat->printWhere(errorMsg, true);
398  std::string what = ex.what();
399  size_t pos = what.find_first_of('\n');
400  do {
401  errorMsg << " " << what.substr(0, pos) << endl;
402  what = what.substr(pos + 1, std::string::npos);
403  pos = what.find_first_of('\n');
404  } while (pos != std::string::npos);
405  errorMsg << " " << what << endl;
406 
407  MPI_Abort(MPI_COMM_WORLD, -100);
408  } catch(SDDSParserException &ex) {
409  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
410 
411  errorMsg << "\n*** Error detected by function \""
412  << ex.where() << "\"\n";
413  std::string what = ex.what();
414  size_t pos = what.find_first_of('\n');
415  do {
416  errorMsg << " " << what.substr(0, pos) << endl;
417  what = what.substr(pos + 1, std::string::npos);
418  pos = what.find_first_of('\n');
419  } while (pos != std::string::npos);
420  errorMsg << " " << what << endl;
421 
422  MPI_Abort(MPI_COMM_WORLD, -100);
423  } catch(IpplException &ex) {
424  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
425 
426  errorMsg << "\n*** Error detected by function \""
427  << ex.where() << "\"\n";
428  std::string what = ex.what();
429  size_t pos = what.find_first_of('\n');
430  do {
431  errorMsg << " " << what.substr(0, pos) << endl;
432  what = what.substr(pos + 1, std::string::npos);
433  pos = what.find_first_of('\n');
434  } while (pos != std::string::npos);
435  errorMsg << " " << what << endl;
436 
437  MPI_Abort(MPI_COMM_WORLD, -100);
438  } catch(std::bad_alloc &ex) {
439  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
440  errorMsg << "\n*** Error:\n";
441  errorMsg << " Sorry, virtual memory exhausted.\n"
442  << ex.what()
443  << endl;
444 
445  MPI_Abort(MPI_COMM_WORLD, -100);
446  } catch(assertion &ex) {
447  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
448  errorMsg << "\n*** Runtime-error ******************\n";
449  std::string what = ex.what();
450  size_t pos = what.find_first_of('\n');
451  do {
452  errorMsg << " " << what.substr(0, pos) << endl;
453  what = what.substr(pos + 1, std::string::npos);
454  pos = what.find_first_of('\n');
455  } while (pos != std::string::npos);
456  errorMsg << " " << what << endl;
457 
458  errorMsg << "\n************************************\n" << endl;
459  throw std::runtime_error("in Parser");
460  } catch(std::exception &ex) {
461  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
462  errorMsg << "\n"
463  << "*** Error:\n"
464  << " Internal OPAL error: \n";
465  std::string what = ex.what();
466  size_t pos = what.find_first_of('\n');
467  do {
468  errorMsg << " " << what.substr(0, pos) << endl;
469  what = what.substr(pos + 1, std::string::npos);
470  pos = what.find_first_of('\n');
471  } while (pos != std::string::npos);
472  errorMsg << " " << what << endl;
473 
474  MPI_Abort(MPI_COMM_WORLD, -100);
475  } catch(...) {
476  Inform errorMsg("Error", std::cerr, INFORM_ALL_NODES);
477  errorMsg << "\n*** Error:\n"
478  << " Unexpected exception caught.\n" << endl;
479 
480  MPI_Abort(MPI_COMM_WORLD, -100);
481  }
482 
483 
484  IpplTimings::stopTimer(mainTimer);
485 
487 
488  IpplTimings::print(std::string("timing.dat"),
489  OpalData::getInstance()->getProblemCharacteristicValues());
490 
491  Ippl::Comm->barrier();
494  delete gmsg;
495 
496 #ifdef ENABLE_AMR
497  if ( initAMR ) {
498  amrex::Finalize(true);
499  }
500 #endif
501 
502  delete ippl;
503  delete Ippl::Info;
504  delete Ippl::Warn;
505  delete Ippl::Error;
506  delete Ippl::Debug;
507 
508  return 0;
509 }
void handleGSLErrors(const char *reason, const char *file, int, int)
int main(int argc, char *argv[])
Definition: Main.cpp:127
Ippl * ippl
Definition: Main.cpp:61
bool checkInitAmrFlag(int argc, char *argv[])
Definition: Main.cpp:113
Inform * gmsg
Definition: Main.cpp:62
#define OPAL_COMPILE_OPTIONS
Definition: OPALconfig.h:11
#define PACKAGE_BUGREPORT
Definition: OPALconfig.h:14
#define OPAL_PROJECT_VERSION
Definition: OPALconfig.h:5
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level5(Inform &inf)
Definition: Inform.cpp:49
#define INFORM_ALL_NODES
Definition: Inform.h:39
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
IpplInfo Ippl
Definition: IpplInfo.h:353
#define INFOMSG(msg)
Definition: IpplInfo.h:348
bool echo
Echo flag.
Definition: Options.cpp:26
std::string getGitRevision()
Definition: Util.cpp:18
void configure()
Configure all commands.
Definition: Configure.cpp:245
FRONT * fs
Definition: hypervolume.cpp:59
The global OPAL structure.
Definition: OpalData.h:49
void storeInputFn(const std::string &fn)
store opals input filename
Definition: OpalData.cpp:638
std::string getInputBasename()
get input file name without extension
Definition: OpalData.cpp:658
void setRestartRun(const bool &value=true)
set OPAL in restart mode
Definition: OpalData.cpp:315
static void deleteInstance()
Definition: OpalData.cpp:205
void setRestartFileName(std::string s)
store opals restart h5 format filename
Definition: OpalData.cpp:331
static OpalData * getInstance()
Definition: OpalData.cpp:195
void storeArguments(int argc, char *argv[])
Definition: OpalData.cpp:752
void setRestartStep(int s)
store the location where to restart
Definition: OpalData.cpp:319
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition: OpalData.cpp:650
bool inRestartRun()
true if we do a restart run
Definition: OpalData.cpp:311
static void clearDictionary()
Definition: Fieldmap.cpp:275
static void setGlobalTruncOrder(int order)
Set the global truncation order.
Definition: FTps.hpp:419
A stream of input tokens.
Definition: FileStream.h:32
static void setEcho(bool flag)
Set echo flag.
Definition: FileStream.cpp:47
The abstract base class for all exceptions in CLASSIC.
The default parser for OPAL-9.
Definition: OpalParser.h:44
virtual void run() const
Read current stream.
Definition: OpalParser.cpp:602
virtual const std::string & what() const
Return the message string for the exception.
virtual const std::string & where() const
Return the name of the method or function which detected the exception.
The base class for all OPAL exceptions.
Definition: OpalException.h:28
std::string date() const
Return date.
Definition: Timer.cpp:35
std::string time() const
Return time.
Definition: Timer.cpp:42
void barrier(void)
Definition: Inform.h:42
static void printVersion(void)
Definition: IpplInfo.cpp:736
static Inform * Warn
Definition: IpplInfo.h:79
static void printHelp()
Definition: IpplInfo.cpp:744
static Inform * Info
Definition: IpplInfo.h:78
static Inform * Error
Definition: IpplInfo.h:80
static MPI_Comm getComm()
Definition: IpplInfo.h:152
static Inform * Debug
Definition: IpplInfo.h:81
static int myNode()
Definition: IpplInfo.cpp:691
static Communicate * Comm
Definition: IpplInfo.h:84
static const char * compileOptions()
Definition: IpplInfo.cpp:836
Timing::TimerRef TimerRef
Definition: IpplTimings.h:176
static TimerRef getTimer(const char *nm)
Definition: IpplTimings.h:182
static void stopTimer(TimerRef t)
Definition: IpplTimings.h:192
static void print()
Definition: IpplTimings.h:207
static void startTimer(TimerRef t)
Definition: IpplTimings.h:187