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{
35 long long operator() () const noexcept requires (N==0)
36 {
37 AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, nullptr);))
38 AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, nullptr);))
39 }
40
46 template <std::integral... Ts>
47 requires (N > 0 && sizeof...(Ts) == N)
49 long long operator() (Ts... var) const noexcept
50 {
51 amrex::GpuArray<long long,N> l_var{var...};
52 AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, l_var.data());))
53 AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, l_var.data());))
54 }
55
61 long long operator() (GpuArray<long long, N> const& var) const noexcept
62 {
63 AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, var.data());))
64 AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, var.data());))
65 }
66
69 explicit operator bool () const {
70 AMREX_IF_ON_DEVICE((return m_device_executor != nullptr;))
71 AMREX_IF_ON_HOST((return m_host_executor != nullptr;))
72 }
73
74 char* m_host_executor = nullptr;
75#ifdef AMREX_USE_GPU
76 char* m_device_executor = nullptr;
77#endif
78};
79
81
93{
94public:
99 IParser (std::string const& func_body);
101 IParser () = default;
106 void define (std::string const& func_body);
107
109 explicit operator bool () const;
110
116 void setConstant (std::string const& name, long long c);
117
123 void registerVariables (Vector<std::string> const& vars);
124
126 void print () const;
127
132 [[nodiscard]] int depth () const;
137 [[nodiscard]] int maxStackSize () const;
138
143 [[nodiscard]] std::string expr () const;
144
149 [[nodiscard]] std::set<std::string> symbols () const;
150
155 template <int N> [[nodiscard]] IParserExecutor<N> compile () const;
156
161 template <int N> [[nodiscard]] IParserExecutor<N> compileHost () const;
162
163private:
164
166 struct Data {
167 std::string m_expression;
168 struct amrex_iparser* m_iparser = nullptr;
169 int m_nvars = 0;
170 bool m_use_arena = true;
171 char* m_host_executor = nullptr;
172#ifdef AMREX_USE_GPU
173 char* m_device_executor = nullptr;
174#endif
175 int m_max_stack_size = 0;
176 int m_exe_size = 0;
177 Data () = default;
178 ~Data ();
179 Data (Data const&) = delete;
180 Data (Data &&) = delete;
181 Data& operator= (Data const&) = delete;
182 Data& operator= (Data &&) = delete;
183 };
185
186 std::shared_ptr<Data> m_data;
187};
188
189template <int N>
190IParserExecutor<N>
192{
193 if (m_data && m_data->m_iparser) {
194 AMREX_ALWAYS_ASSERT(N == m_data->m_nvars);
195
196 if (!(m_data->m_host_executor)) {
197 int stack_size;
198 m_data->m_exe_size = static_cast<int>
199 (iparser_exe_size(m_data->m_iparser, m_data->m_max_stack_size,
200 stack_size));
201
202 if (m_data->m_max_stack_size > AMREX_IPARSER_STACK_SIZE) {
203 amrex::Abort("amrex::IParser: AMREX_IPARSER_STACK_SIZE, "
204 + std::to_string(AMREX_IPARSER_STACK_SIZE) + ", is too small for "
205 + m_data->m_expression);
206 }
207 if (stack_size != 0) {
208 amrex::Abort("amrex::IParser: something went wrong with iparser stack! "
209 + std::to_string(stack_size));
210 }
211
212 m_data->m_host_executor = (char*)The_Pinned_Arena()->alloc(m_data->m_exe_size);
213 if (m_data->m_host_executor == nullptr) { // Arena is not ready yet
214 m_data->m_host_executor = (char*) std::malloc(m_data->m_exe_size);
215 m_data->m_use_arena = false;
216 }
217
218 try {
219 iparser_compile(m_data->m_iparser, m_data->m_host_executor);
220 } catch (const std::runtime_error& e) {
221 throw std::runtime_error(std::string(e.what()) + " in IParser expression \""
222 + m_data->m_expression + "\"");
223 }
224 }
225
226#ifdef AMREX_USE_GPU
227 return IParserExecutor<N>{m_data->m_host_executor, m_data->m_device_executor};
228#else
229 return IParserExecutor<N>{m_data->m_host_executor};
230#endif
231 } else {
232 return IParserExecutor<N>{};
233 }
234}
235
236template <int N>
239{
240 auto exe = compileHost<N>();
241
242#ifdef AMREX_USE_GPU
243 if (m_data && m_data->m_iparser && !(m_data->m_device_executor)
244 && m_data->m_use_arena)
245 {
246 m_data->m_device_executor = (char*)The_Arena()->alloc(m_data->m_exe_size);
247 Gpu::htod_memcpy_async(m_data->m_device_executor, m_data->m_host_executor,
248 m_data->m_exe_size);
250 exe.m_device_executor = m_data->m_device_executor;
251 }
252#endif
253
254 return exe;
255}
256
257}
258
259#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:93
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:191
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:238
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:29
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:76
__host__ __device__ long long operator()() const noexcept
Evaluate constant expressions (N == 0) and return the integer result.
Definition AMReX_IParser.H:35
char * m_host_executor
Pointer to host bytecode.
Definition AMReX_IParser.H:74