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