Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_IParser.H
Go to the documentation of this file.
1#ifndef AMREX_IPARSER_H_
2#define AMREX_IPARSER_H_
3
9#include <AMReX_Arena.H>
10#include <AMReX_Array.H>
11#include <AMReX_GpuDevice.H>
12#include <AMReX_IParser_Exe.H>
13#include <AMReX_Vector.H>
14
15#include <memory>
16#include <string>
17#include <set>
18
19namespace amrex {
20
28template <int N>
30{
34 template <int M=N, std::enable_if_t<M==0,int> = 0>
36 long long operator() () const noexcept
37 {
38 AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, nullptr);))
39 AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, nullptr);))
40 }
41
47 template <typename... Ts>
49 std::enable_if_t<sizeof...(Ts) == N && std::conjunction_v<std::is_integral<Ts>...>,
50 long long>
51 operator() (Ts... var) const noexcept
52 {
53 amrex::GpuArray<long long,N> l_var{var...};
54 AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, l_var.data());))
55 AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, l_var.data());))
56 }
57
63 long long operator() (GpuArray<long long, N> const& var) const noexcept
64 {
65 AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, var.data());))
66 AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, var.data());))
67 }
68
71 explicit operator bool () const {
72 AMREX_IF_ON_DEVICE((return m_device_executor != nullptr;))
73 AMREX_IF_ON_HOST((return m_host_executor != nullptr;))
74 }
75
76 char* m_host_executor = nullptr;
77#ifdef AMREX_USE_GPU
78 char* m_device_executor = nullptr;
79#endif
80};
81
83
95{
96public:
101 IParser (std::string const& func_body);
103 IParser () = default;
108 void define (std::string const& func_body);
109
111 explicit operator bool () const;
112
118 void setConstant (std::string const& name, long long c);
119
125 void registerVariables (Vector<std::string> const& vars);
126
128 void print () const;
129
134 [[nodiscard]] int depth () const;
139 [[nodiscard]] int maxStackSize () const;
140
145 [[nodiscard]] std::string expr () const;
146
151 [[nodiscard]] std::set<std::string> symbols () const;
152
157 template <int N> [[nodiscard]] IParserExecutor<N> compile () const;
158
163 template <int N> [[nodiscard]] IParserExecutor<N> compileHost () const;
164
165private:
166
168 struct Data {
169 std::string m_expression;
170 struct amrex_iparser* m_iparser = nullptr;
171 int m_nvars = 0;
172 bool m_use_arena = true;
173 char* m_host_executor = nullptr;
174#ifdef AMREX_USE_GPU
175 char* m_device_executor = nullptr;
176#endif
177 int m_max_stack_size = 0;
178 int m_exe_size = 0;
179 Data () = default;
180 ~Data ();
181 Data (Data const&) = delete;
182 Data (Data &&) = delete;
183 Data& operator= (Data const&) = delete;
184 Data& operator= (Data &&) = delete;
185 };
187
188 std::shared_ptr<Data> m_data;
189};
190
191template <int N>
192IParserExecutor<N>
194{
195 if (m_data && m_data->m_iparser) {
196 AMREX_ALWAYS_ASSERT(N == m_data->m_nvars);
197
198 if (!(m_data->m_host_executor)) {
199 int stack_size;
200 m_data->m_exe_size = static_cast<int>
201 (iparser_exe_size(m_data->m_iparser, m_data->m_max_stack_size,
202 stack_size));
203
204 if (m_data->m_max_stack_size > AMREX_IPARSER_STACK_SIZE) {
205 amrex::Abort("amrex::IParser: AMREX_IPARSER_STACK_SIZE, "
206 + std::to_string(AMREX_IPARSER_STACK_SIZE) + ", is too small for "
207 + m_data->m_expression);
208 }
209 if (stack_size != 0) {
210 amrex::Abort("amrex::IParser: something went wrong with iparser stack! "
211 + std::to_string(stack_size));
212 }
213
214 m_data->m_host_executor = (char*)The_Pinned_Arena()->alloc(m_data->m_exe_size);
215 if (m_data->m_host_executor == nullptr) { // Arena is not ready yet
216 m_data->m_host_executor = (char*) std::malloc(m_data->m_exe_size);
217 m_data->m_use_arena = false;
218 }
219
220 try {
221 iparser_compile(m_data->m_iparser, m_data->m_host_executor);
222 } catch (const std::runtime_error& e) {
223 throw std::runtime_error(std::string(e.what()) + " in IParser expression \""
224 + m_data->m_expression + "\"");
225 }
226 }
227
228#ifdef AMREX_USE_GPU
229 return IParserExecutor<N>{m_data->m_host_executor, m_data->m_device_executor};
230#else
231 return IParserExecutor<N>{m_data->m_host_executor};
232#endif
233 } else {
234 return IParserExecutor<N>{};
235 }
236}
237
238template <int N>
241{
242 auto exe = compileHost<N>();
243
244#ifdef AMREX_USE_GPU
245 if (m_data && m_data->m_iparser && !(m_data->m_device_executor)
246 && m_data->m_use_arena)
247 {
248 m_data->m_device_executor = (char*)The_Arena()->alloc(m_data->m_exe_size);
249 Gpu::htod_memcpy_async(m_data->m_device_executor, m_data->m_host_executor,
250 m_data->m_exe_size);
252 exe.m_device_executor = m_data->m_device_executor;
253 }
254#endif
255
256 return exe;
257}
258
259}
260
261#endif
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:119
#define AMREX_IF_ON_DEVICE(CODE)
Definition AMReX_GpuQualifiers.H:56
#define AMREX_IF_ON_HOST(CODE)
Definition AMReX_GpuQualifiers.H:58
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
virtual void * alloc(std::size_t sz)=0
Integer-only variant of amrex::Parser.
Definition AMReX_IParser.H:95
void print() const
Print the parse tree to stdout for debugging.
Definition AMReX_IParser.cpp:101
std::set< std::string > symbols() const
Return the set of symbols referenced by the expression.
Definition AMReX_IParser.cpp:139
void setConstant(std::string const &name, long long c)
Bind a named integer constant.
Definition AMReX_IParser.cpp:75
IParserExecutor< N > compileHost() const
Compile the expression into a host-only executor.
Definition AMReX_IParser.H:193
std::string expr() const
Return the sanitized expression string.
Definition AMReX_IParser.cpp:129
IParserExecutor< N > compile() const
Compile the expression into a host/device IParserExecutor.
Definition AMReX_IParser.H:240
void registerVariables(Vector< std::string > const &vars)
Register the ordered list of integer variables referenced by the expression.
Definition AMReX_IParser.cpp:86
int depth() const
Return the maximum parse-tree depth.
Definition AMReX_IParser.cpp:109
void define(std::string const &func_body)
Parse and own a new integer expression, replacing any previous state.
Definition AMReX_IParser.cpp:24
IParser()=default
Default-construct; call define() before compile().
int maxStackSize() const
Return the maximum parser stack usage.
Definition AMReX_IParser.cpp:119
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:28
Arena * The_Pinned_Arena()
Definition AMReX_Arena.cpp:860
Arena * The_Arena()
Definition AMReX_Arena.cpp:820
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:310
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:421
Definition AMReX_Amr.cpp:50
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:241
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:43
Callable wrapper around an integer parser expression with N variables.
Definition AMReX_IParser.H:30
char * m_device_executor
Pointer to device bytecode (if copied).
Definition AMReX_IParser.H:78
__host__ __device__ long long operator()() const noexcept
Evaluate constant expressions (N == 0) and return the integer result.
Definition AMReX_IParser.H:36
char * m_host_executor
Pointer to host bytecode.
Definition AMReX_IParser.H:76