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 44 : void initialize(int& argc, char* argv[], MPI_Comm comm) {
17 44 : Env = std::make_unique<mpi::Environment>(argc, argv, comm);
18 :
19 44 : Comm = std::make_unique<mpi::Communicator>(comm);
20 :
21 44 : Info = std::make_unique<Inform>("Ippl");
22 44 : Warn = std::make_unique<Inform>("Warning", std::cerr);
23 44 : Error = std::make_unique<Inform>("Error", std::cerr, INFORM_ALL_NODES);
24 :
25 : try {
26 44 : std::list<std::string> notparsed;
27 44 : int infoLevel = 0;
28 44 : int nargs = 0;
29 88 : while (nargs < argc) {
30 44 : 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 44 : } 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 44 : } 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 44 : } 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 44 : } 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 44 : } else if (nargs > 0 && std::strstr(argv[nargs], "--kokkos") == nullptr) {
75 0 : notparsed.push_back(argv[nargs]);
76 : }
77 44 : ++nargs;
78 : }
79 :
80 44 : Info->setOutputLevel(infoLevel);
81 44 : Error->setOutputLevel(0);
82 44 : Warn->setOutputLevel(0);
83 :
84 44 : if (infoLevel > 0 && Comm->rank() == 0) {
85 0 : for (auto& l : notparsed) {
86 0 : std::cout << "Warning: Option '" << l << "' is not parsed by Ippl."
87 0 : << std::endl;
88 : }
89 : }
90 44 : } catch (const std::exception& e) {
91 0 : if (Comm->rank() == 0) {
92 0 : std::cerr << e.what() << std::endl;
93 : }
94 0 : std::exit(0);
95 0 : }
96 :
97 44 : Kokkos::initialize(argc, argv);
98 44 : }
99 :
100 44 : void finalize() {
101 44 : Comm->deleteAllBuffers();
102 44 : Kokkos::finalize();
103 : // we must first delete the communicator and
104 : // afterwards the MPI environment
105 44 : Comm.reset(nullptr);
106 44 : Env.reset(nullptr);
107 44 : }
108 :
109 0 : void fence() {
110 0 : Kokkos::fence();
111 0 : }
112 :
113 0 : void abort(const char* msg, int errorcode) {
114 0 : if (msg) {
115 0 : *Error << msg << endl;
116 : }
117 0 : Comm->abort(errorcode);
118 0 : }
119 :
120 : namespace detail {
121 220 : bool checkOption(const char* arg, const char* lstr, const char* sstr) {
122 220 : return (std::strcmp(arg, lstr) == 0) || (std::strcmp(arg, sstr) == 0);
123 : }
124 :
125 : template <typename T, typename>
126 0 : T getNumericalOption(const char* arg) {
127 0 : constexpr bool isInt = std::is_integral_v<T>;
128 0 : std::string sarg = arg;
129 : try {
130 : T ret;
131 : size_t parsed;
132 : if constexpr (isInt) {
133 0 : ret = std::stoll(sarg, &parsed);
134 : } else {
135 0 : ret = std::stold(sarg, &parsed);
136 : }
137 0 : if (parsed != sarg.length())
138 0 : throw std::invalid_argument("Failed to parse");
139 0 : return ret;
140 0 : } catch (std::invalid_argument& e) {
141 : if constexpr (isInt) {
142 0 : throw std::runtime_error("Expected integer argument!");
143 : } else {
144 0 : throw std::runtime_error("Expected floating point argument!");
145 : }
146 : }
147 : // Silence nvcc warning: missing return statement at end of non-void function
148 : throw std::runtime_error("Unreachable state");
149 0 : }
150 : } // namespace detail
151 : } // namespace ippl
|