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
91{
92public:
97 IParser (std::string const& func_body);
99 IParser () = default;
104 void define (std::string const& func_body);
105
107 explicit operator bool () const;
108
114 void setConstant (std::string const& name, long long c);
115
121 void registerVariables (Vector<std::string> const& vars);
122
124 void print () const;
125
130 [[nodiscard]] int depth () const;
135 [[nodiscard]] int maxStackSize () const;
136
141 [[nodiscard]] std::string expr () const;
142
147 [[nodiscard]] std::set<std::string> symbols () const;
148
153 template <int N> [[nodiscard]] IParserExecutor<N> compile () const;
154
159 template <int N> [[nodiscard]] IParserExecutor<N> compileHost () const;
160
161private:
162
164 struct Data {
165 std::string m_expression;
166 struct amrex_iparser* m_iparser = nullptr;
167 int m_nvars = 0;
168 bool m_use_arena = true;
169 char* m_host_executor = nullptr;
170#ifdef AMREX_USE_GPU
171 char* m_device_executor = nullptr;
172#endif
173 int m_max_stack_size = 0;
174 int m_exe_size = 0;
175 Data () = default;
176 ~Data ();
177 Data (Data const&) = delete;
178 Data (Data &&) = delete;
179 Data& operator= (Data const&) = delete;
180 Data& operator= (Data &&) = delete;
181 };
183
184 std::shared_ptr<Data> m_data;
185};
186
187template <int N>
188IParserExecutor<N>
190{
191 if (m_data && m_data->m_iparser) {
192 AMREX_ALWAYS_ASSERT(N == m_data->m_nvars);
193
194 if (!(m_data->m_host_executor)) {
195 int stack_size;
196 m_data->m_exe_size = static_cast<int>
197 (iparser_exe_size(m_data->m_iparser, m_data->m_max_stack_size,
198 stack_size));
199
200 if (m_data->m_max_stack_size > AMREX_IPARSER_STACK_SIZE) {
201 amrex::Abort("amrex::IParser: AMREX_IPARSER_STACK_SIZE, "
202 + std::to_string(AMREX_IPARSER_STACK_SIZE) + ", is too small for "
203 + m_data->m_expression);
204 }
205 if (stack_size != 0) {
206 amrex::Abort("amrex::IParser: something went wrong with iparser stack! "
207 + std::to_string(stack_size));
208 }
209
210 m_data->m_host_executor = (char*)The_Pinned_Arena()->alloc(m_data->m_exe_size);
211 if (m_data->m_host_executor == nullptr) { // Arena is not ready yet
212 m_data->m_host_executor = (char*) std::malloc(m_data->m_exe_size);
213 m_data->m_use_arena = false;
214 }
215
216 try {
217 iparser_compile(m_data->m_iparser, m_data->m_host_executor);
218 } catch (const std::runtime_error& e) {
219 throw std::runtime_error(std::string(e.what()) + " in IParser expression \""
220 + m_data->m_expression + "\"");
221 }
222 }
223
224#ifdef AMREX_USE_GPU
225 return IParserExecutor<N>{m_data->m_host_executor, m_data->m_device_executor};
226#else
227 return IParserExecutor<N>{m_data->m_host_executor};
228#endif
229 } else {
230 return IParserExecutor<N>{};
231 }
232}
233
234template <int N>
237{
238 auto exe = compileHost<N>();
239
240#ifdef AMREX_USE_GPU
241 if (m_data && m_data->m_iparser && !(m_data->m_device_executor)
242 && m_data->m_use_arena)
243 {
244 m_data->m_device_executor = (char*)The_Arena()->alloc(m_data->m_exe_size);
245 Gpu::htod_memcpy_async(m_data->m_device_executor, m_data->m_host_executor,
246 m_data->m_exe_size);
248 exe.m_device_executor = m_data->m_device_executor;
249 }
250#endif
251
252 return exe;
253}
254
255}
256
257#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:91
void print() const
Print the parse tree to stdout for debugging.
Definition AMReX_IParser.cpp:86
std::set< std::string > symbols() const
Return the set of symbols referenced by the expression.
Definition AMReX_IParser.cpp:124
void setConstant(std::string const &name, long long c)
Bind a named integer constant.
Definition AMReX_IParser.cpp:67
IParserExecutor< N > compileHost() const
Compile the expression into a host-only executor.
Definition AMReX_IParser.H:189
std::string expr() const
Return the sanitized expression string.
Definition AMReX_IParser.cpp:114
IParserExecutor< N > compile() const
Compile the expression into a host/device IParserExecutor.
Definition AMReX_IParser.H:236
void registerVariables(Vector< std::string > const &vars)
Register the ordered list of integer variables referenced by the expression.
Definition AMReX_IParser.cpp:75
int depth() const
Return the maximum parse-tree depth.
Definition AMReX_IParser.cpp:94
void define(std::string const &func_body)
Parse and own a new integer expression, replacing any previous state.
Definition AMReX_IParser.cpp:18
IParser()=default
Default-construct; call define() before compile().
int maxStackSize() const
Return the maximum parser stack usage.
Definition AMReX_IParser.cpp:104
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:845
Arena * The_Arena()
Definition AMReX_Arena.cpp:805
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:49
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition AMReX.cpp:240
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