Line data Source code
1 :
2 : #ifndef BL_AMREX_H
3 : #define BL_AMREX_H
4 : #include <AMReX_Config.H>
5 :
6 : #include <AMReX_GpuQualifiers.H>
7 : #include <AMReX_GpuPrint.H>
8 : #include <AMReX_GpuAssert.H>
9 : #include <AMReX_ccse-mpi.H>
10 : #include <AMReX_Exception.H>
11 : #include <AMReX_Extension.H>
12 :
13 : #include <cstdint>
14 : #include <functional>
15 : #include <iostream>
16 : #include <memory>
17 : #include <string>
18 : #include <type_traits>
19 : #include <vector>
20 :
21 : //
22 : // Initialize, Finalize, Error Reporting, and Version String Functions
23 :
24 : /*
25 : This class consists of initialize, finalize, error-reporting, and version
26 : functions that are used throughout AMReX. Note that all the output functions
27 : add a terminating exclamation mark, so there is no need to add any punctuation
28 : to sentences that get output explicitly.
29 : */
30 :
31 : namespace amrex
32 : {
33 : class AMReX;
34 :
35 : using PTR_TO_VOID_FUNC = void (*)();
36 : using ErrorHandler = void (*)(const char*);
37 :
38 : namespace system
39 : {
40 : #ifndef AMREX_DEBUG
41 : constexpr bool NDebug = true;
42 : constexpr bool Debug = false;
43 : #else
44 : constexpr bool NDebug = false;
45 : constexpr bool Debug = true;
46 : #endif
47 :
48 : extern AMREX_EXPORT std::string exename;
49 :
50 : extern AMREX_EXPORT int verbose;
51 :
52 : extern AMREX_EXPORT int signal_handling;
53 : extern AMREX_EXPORT int handle_sigsegv;
54 : extern AMREX_EXPORT int handle_sigterm;
55 : extern AMREX_EXPORT int handle_sigint;
56 : extern AMREX_EXPORT int handle_sigabrt;
57 : extern AMREX_EXPORT int handle_sigfpe;
58 :
59 : extern AMREX_EXPORT int call_addr2line;
60 : extern AMREX_EXPORT int throw_exception;
61 :
62 : extern AMREX_EXPORT int regtest_reduction;
63 :
64 : extern AMREX_EXPORT std::ostream* osout;
65 : extern AMREX_EXPORT std::ostream* oserr;
66 :
67 : extern AMREX_EXPORT ErrorHandler error_handler;
68 : extern AMREX_EXPORT int abort_on_unused_inputs;
69 :
70 : extern AMREX_EXPORT bool init_snan;
71 : }
72 :
73 : /** the AMReX "git describe" version */
74 : [[nodiscard]] std::string Version ();
75 :
76 : // The returned AMReX* is non-owning! To delete it, call Finalize(AMReX*).
77 : AMReX* Initialize (MPI_Comm mpi_comm,
78 : std::ostream& a_osout = std::cout,
79 : std::ostream& a_oserr = std::cerr,
80 : ErrorHandler a_errhandler = nullptr);
81 :
82 : // The returned AMReX* is non-owning! To delete it, call Finalize(AMReX*).
83 : AMReX* Initialize (int& argc, char**& argv, bool build_parm_parse=true,
84 : MPI_Comm mpi_comm = MPI_COMM_WORLD,
85 : const std::function<void()>& func_parm_parse = {},
86 : std::ostream& a_osout = std::cout,
87 : std::ostream& a_oserr = std::cerr,
88 : ErrorHandler a_errhandler = nullptr);
89 :
90 : /**
91 : \brief Returns true if there are any currently-active and initialized
92 : AMReX instances (i.e. one for which amrex::Initialize has been called,
93 : and amrex::Finalize has not). Otherwise false.
94 : */
95 : [[nodiscard]] bool Initialized ();
96 :
97 : void Finalize (AMReX* pamrex);
98 : void Finalize (); // Finalize the current top
99 : /**
100 : * \brief We maintain a stack of functions that need to be called in Finalize().
101 : * The functions are called in LIFO order. The idea here is to allow
102 : * classes to clean up any "global" state that they maintain when we're
103 : * exiting from AMReX.
104 : */
105 : void ExecOnFinalize (PTR_TO_VOID_FUNC);
106 : void ExecOnInitialize (PTR_TO_VOID_FUNC);
107 :
108 : //! This shuts up the compiler about unused variables
109 : template <class... Ts>
110 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
111 23528 : void ignore_unused (const Ts&...) {}
112 :
113 : //! Print out message to cerr and exit via amrex::Abort().
114 : void Error (const std::string& msg);
115 :
116 : void Error_host (const char* type, const char* msg);
117 :
118 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
119 : void Error (const char* msg = nullptr) {
120 : #if defined(NDEBUG)
121 : AMREX_IF_ON_DEVICE((amrex::ignore_unused(msg);))
122 : #else
123 : AMREX_IF_ON_DEVICE((
124 : if (msg) { AMREX_DEVICE_PRINTF("Error %s\n", msg); }
125 : AMREX_DEVICE_ASSERT(0);
126 : ))
127 : #endif
128 : AMREX_IF_ON_HOST((Error_host("Error", msg);))
129 : }
130 :
131 : //! Print out warning message to cerr.
132 : void Warning (const std::string& msg);
133 :
134 : void Warning_host (const char * msg);
135 :
136 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
137 : void Warning (const char * msg) {
138 : #if defined(NDEBUG)
139 : AMREX_IF_ON_DEVICE((amrex::ignore_unused(msg);))
140 : #else
141 : AMREX_IF_ON_DEVICE((if (msg) { AMREX_DEVICE_PRINTF("Warning %s\n", msg); }))
142 : #endif
143 0 : AMREX_IF_ON_HOST((Warning_host(msg);))
144 0 : }
145 :
146 : //! Print out message to cerr and exit via abort().
147 : void Abort (const std::string& msg);
148 :
149 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
150 : void Abort (const char * msg = nullptr) {
151 : #if defined(NDEBUG)
152 : AMREX_IF_ON_DEVICE((amrex::ignore_unused(msg);))
153 : #else
154 : AMREX_IF_ON_DEVICE((
155 : if (msg) { AMREX_DEVICE_PRINTF("Abort %s\n", msg); }
156 : AMREX_DEVICE_ASSERT(0);
157 : ))
158 : #endif
159 0 : AMREX_IF_ON_HOST((Error_host("Abort", msg);))
160 0 : }
161 :
162 : /**
163 : * \brief Prints assertion failed messages to cerr and exits
164 : * via abort(). Intended for use by the BL_ASSERT() macro
165 : * in <AMReX_BLassert.H>.
166 : */
167 :
168 : void Assert_host (const char* EX, const char* file, int line, const char* msg);
169 :
170 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
171 : void Assert (const char* EX, const char* file, int line, const char* msg = nullptr) {
172 : #if defined(NDEBUG)
173 : AMREX_IF_ON_DEVICE((amrex::ignore_unused(EX,file,line,msg);))
174 : #else
175 : AMREX_IF_ON_DEVICE((
176 : if (msg) {
177 : AMREX_DEVICE_PRINTF("Assertion `%s' failed, file \"%s\", line %d, Msg: %s",
178 : EX, file, line, msg);
179 : } else {
180 : AMREX_DEVICE_PRINTF("Assertion `%s' failed, file \"%s\", line %d",
181 : EX, file, line);
182 : }
183 : AMREX_DEVICE_ASSERT(0);
184 : ))
185 : #endif
186 0 : AMREX_IF_ON_HOST((Assert_host(EX,file,line,msg);))
187 0 : }
188 :
189 : /**
190 : * \brief This is used by amrex::Error(), amrex::Abort(), and amrex::Assert()
191 : * to ensure that when writing the message to stderr, that no additional
192 : * heap-based memory is allocated.
193 : */
194 : void write_to_stderr_without_buffering (const char* str);
195 :
196 : void SetErrorHandler (ErrorHandler f);
197 :
198 : std::ostream& OutStream ();
199 : std::ostream& ErrorStream ();
200 :
201 : [[nodiscard]] int Verbose () noexcept;
202 : void SetVerbose (int v) noexcept;
203 :
204 : [[nodiscard]] bool InitSNaN () noexcept;
205 : void SetInitSNaN (bool v) noexcept;
206 :
207 : // ! Get the entire command line including the executable
208 : [[nodiscard]] std::string get_command ();
209 :
210 : // ! Get number of command line arguments after the executable
211 : [[nodiscard]] int command_argument_count ();
212 :
213 : /**
214 : * \brief Get command line arguments. The executable name is the
215 : * zero-th argument. Return empty string if there are not that
216 : * many arguments. std::string
217 : */
218 : [[nodiscard]] std::string get_command_argument (int number);
219 :
220 : #ifndef _MSC_VER
221 : inline void GccPlacater ()
222 : {
223 : std::allocator<bool> a_b;
224 : std::allocator<char> a_c;
225 : std::allocator<int> a_i;
226 : std::allocator<long> a_l;
227 : std::allocator<long long> a_ll;
228 : std::allocator<unsigned char> a_uc;
229 : std::allocator<unsigned int> a_ui;
230 : std::allocator<unsigned long> a_ul;
231 : std::allocator<unsigned long long> a_ull;
232 : std::allocator<float> a_f;
233 : std::allocator<double> a_d;
234 : std::allocator<std::string> a_s;
235 :
236 : amrex::ignore_unused(a_b);
237 : amrex::ignore_unused(a_c);
238 : amrex::ignore_unused(a_i);
239 : amrex::ignore_unused(a_l);
240 : amrex::ignore_unused(a_ll);
241 : amrex::ignore_unused(a_uc);
242 : amrex::ignore_unused(a_ui);
243 : amrex::ignore_unused(a_ul);
244 : amrex::ignore_unused(a_ull);
245 : amrex::ignore_unused(a_ll);
246 : amrex::ignore_unused(a_f);
247 : amrex::ignore_unused(a_d);
248 : amrex::ignore_unused(a_s);
249 : }
250 : #endif
251 :
252 : class Geometry;
253 :
254 : class AMReX
255 : {
256 : public:
257 : AMReX ();
258 : ~AMReX ();
259 : AMReX (AMReX const&) = delete;
260 : AMReX (AMReX &&) = delete;
261 : AMReX& operator= (AMReX const&) = delete;
262 : AMReX& operator= (AMReX &&) = delete;
263 :
264 : static bool empty () noexcept { return m_instance.empty(); }
265 :
266 : static int size () noexcept { return static_cast<int>(m_instance.size()); }
267 :
268 : static AMReX* top () noexcept { return m_instance.back().get(); }
269 :
270 : // Thisfunction will take the ownership of the AMReX pointer,
271 : // and put it on the top of the stack (i.e., back of the
272 : // vector). If the pointer is already in the stack, it will
273 : // be moved to the top.
274 : static void push (AMReX* pamrex);
275 :
276 : // This erases `pamrex` from the stack.
277 : static void erase (AMReX* pamrex);
278 :
279 : [[nodiscard]] Geometry* getDefaultGeometry () noexcept { return m_geom; }
280 :
281 : private:
282 :
283 : static AMREX_EXPORT std::vector<std::unique_ptr<AMReX> > m_instance;
284 :
285 : Geometry* m_geom = nullptr;
286 : };
287 :
288 : enum struct FPExcept : std::uint8_t {
289 : none = 0B0000,
290 : invalid = 0B0001,
291 : zero = 0B0010,
292 : overflow = 0B0100,
293 : all = 0B0111
294 : };
295 :
296 : [[nodiscard]] inline bool any (FPExcept a) { return a != FPExcept::none; }
297 :
298 : [[nodiscard]] inline FPExcept operator| (FPExcept a, FPExcept b)
299 : {
300 : using T = std::underlying_type_t<FPExcept>;
301 : return static_cast<FPExcept>(static_cast<T>(a) | static_cast<T>(b));
302 : }
303 :
304 : [[nodiscard]] inline FPExcept operator& (FPExcept a, FPExcept b)
305 : {
306 : using T = std::underlying_type_t<FPExcept>;
307 : return static_cast<FPExcept>(static_cast<T>(a) & static_cast<T>(b));
308 : }
309 :
310 : //! Return currently enabled FP exceptions. Linux only.
311 : [[nodiscard]] FPExcept getFPExcept ();
312 :
313 : //! Set FP exception traps. Linux only. This enables set flags and
314 : //! DISABLES unset flags. This can be used to restore previous settings.
315 : FPExcept setFPExcept (FPExcept excepts);
316 :
317 : /**
318 : * \brief Disable FP exceptions. Linux Only
319 : *
320 : * This function disables given exception traps and keeps the status of
321 : * the others. The example below disables FPE invalid and
322 : * divide-by-zero, and later restores the previous settings.
323 : *
324 : \verbatim
325 : auto prev_excepts = disableFPExcept(FPExcept::invalid | FPExcept::zero);
326 : // ....
327 : setFPExcept(prev_excepts); // restore previous settings
328 : \endverbatim
329 : */
330 : [[nodiscard]] FPExcept disableFPExcept (FPExcept excepts);
331 :
332 : /**
333 : * \brief Enable FP exceptions. Linux Only
334 : *
335 : * This function enables given exception traps and keeps the status of
336 : * the others. The example below enables all FPE traps, and later
337 : * restores the previous settings.
338 : *
339 : \verbatim
340 : auto prev_excepts = disableFPExcept(FPExcept::all);
341 : // ....
342 : setFPExcept(prev_excepts); // restore previous settings
343 : \endverbatim
344 : */
345 : [[nodiscard]] FPExcept enableFPExcept (FPExcept excepts);
346 : }
347 :
348 : #endif /*BL_AMREX_H*/
|