Line data Source code
1 : //
2 : // Class Ippl
3 : // Ippl environment.
4 : //
5 : #include <Kokkos_Core.hpp>
6 : #include "Ippl.h"
7 :
8 : #include <cstdlib>
9 : #include <cstring>
10 : #include <list>
11 :
12 : #include "Utility/IpplInfo.h"
13 :
14 : namespace ippl {
15 :
16 60 : void initialize(int& argc, char* argv[], MPI_Comm comm) {
17 60 : Env = std::make_unique<mpi::Environment>(argc, argv, comm);
18 :
19 60 : Comm = std::make_unique<mpi::Communicator>(comm);
20 :
21 60 : Info = std::make_unique<Inform>("Ippl");
22 60 : Warn = std::make_unique<Inform>("Warning", std::cerr);
23 60 : Error = std::make_unique<Inform>("Error", std::cerr, INFORM_ALL_NODES);
24 :
25 : try {
26 60 : std::list<std::string> notparsed;
27 60 : int infoLevel = 0;
28 60 : int nargs = 0;
29 120 : while (nargs < argc) {
30 60 : if (detail::checkOption(argv[nargs], "--help", "-h")) {
31 0 : if (Comm->rank() == 0) {
32 0 : IpplInfo::printHelp(argv);
33 : }
34 0 : std::exit(0);
35 60 : } else if (detail::checkOption(argv[nargs], "--info", "-i")) {
36 0 : ++nargs;
37 0 : if (nargs >= argc) {
38 0 : throw std::runtime_error("Missing info level value!");
39 : }
40 0 : infoLevel = detail::getNumericalOption<int>(argv[nargs]);
41 60 : } else if (detail::checkOption(argv[nargs], "--timer-fences", "")) {
42 0 : ++nargs;
43 0 : if (nargs >= argc) {
44 0 : throw std::runtime_error("Missing timer fence enable option!");
45 : }
46 0 : if (std::strcmp(argv[nargs], "on") == 0) {
47 0 : Timer::enableFences = true;
48 0 : } else if (std::strcmp(argv[nargs], "off") == 0) {
49 0 : Timer::enableFences = false;
50 : } else {
51 0 : throw std::runtime_error("Invalid timer fence option");
52 : }
53 60 : } else if (detail::checkOption(argv[nargs], "--version", "-v")) {
54 0 : IpplInfo::printVersion();
55 0 : std::string options = IpplInfo::compileOptions();
56 0 : std::string header("Compile-time options: ");
57 0 : while (options.length() > 58) {
58 0 : std::string line = options.substr(0, 58);
59 0 : size_t n = line.find_last_of(' ');
60 0 : *Info << header << line.substr(0, n) << "\n";
61 :
62 0 : header = std::string(22, ' ');
63 0 : options = options.substr(n + 1);
64 0 : }
65 0 : *Info << header << options << endl;
66 0 : std::exit(0);
67 60 : } else if (detail::checkOption(argv[nargs], "--overallocate", "-b")) {
68 0 : ++nargs;
69 0 : if (nargs >= argc) {
70 0 : throw std::runtime_error("Missing overallocation factor value!");
71 : }
72 0 : auto factor = detail::getNumericalOption<double>(argv[nargs]);
73 0 : Comm->setDefaultOverallocation(factor);
74 60 : } else if (nargs > 0 && std::strstr(argv[nargs], "--kokkos") == nullptr) {
75 0 : notparsed.push_back(argv[nargs]);
76 : }
77 60 : ++nargs;
78 : }
79 :
80 60 : Info->setOutputLevel(infoLevel);
81 60 : Error->setOutputLevel(infoLevel);
82 60 : Warn->setOutputLevel(infoLevel);
83 :
84 60 : } catch (const std::exception& e) {
85 0 : if (Comm->rank() == 0) {
86 0 : std::cerr << e.what() << std::endl;
87 : }
88 0 : std::exit(0);
89 0 : }
90 :
91 60 : Kokkos::initialize(argc, argv);
92 60 : }
93 :
94 60 : void finalize() {
95 60 : Comm->deleteAllBuffers();
96 60 : Kokkos::finalize();
97 : // we must first delete the communicator and
98 : // afterwards the MPI environment
99 60 : Comm.reset(nullptr);
100 60 : Env.reset(nullptr);
101 60 : }
102 :
103 0 : void fence() {
104 0 : Kokkos::fence();
105 0 : }
106 :
107 0 : void abort(const char* msg, int errorcode) {
108 0 : if (msg) {
109 0 : *Error << msg << endl;
110 : }
111 0 : Comm->abort(errorcode);
112 0 : }
113 :
114 : namespace detail {
115 300 : bool checkOption(const char* arg, const char* lstr, const char* sstr) {
116 300 : return (std::strcmp(arg, lstr) == 0) || (std::strcmp(arg, sstr) == 0);
117 : }
118 :
119 : template <typename T, typename>
120 0 : T getNumericalOption(const char* arg) {
121 0 : constexpr bool isInt = std::is_integral_v<T>;
122 0 : std::string sarg = arg;
123 : try {
124 : T ret;
125 : size_t parsed;
126 : if constexpr (isInt) {
127 0 : ret = std::stoll(sarg, &parsed);
128 : } else {
129 0 : ret = std::stold(sarg, &parsed);
130 : }
131 0 : if (parsed != sarg.length())
132 0 : throw std::invalid_argument("Failed to parse");
133 0 : return ret;
134 0 : } catch (std::invalid_argument& e) {
135 : if constexpr (isInt) {
136 0 : throw std::runtime_error("Expected integer argument!");
137 : } else {
138 0 : throw std::runtime_error("Expected floating point argument!");
139 : }
140 : }
141 : // Silence nvcc warning: missing return statement at end of non-void function
142 : throw std::runtime_error("Unreachable state");
143 0 : }
144 : } // namespace detail
145 : } // namespace ippl
|