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