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