Block-Structured AMR Software Framework
AMReX_IParser.H
Go to the documentation of this file.
1 #ifndef AMREX_IPARSER_H_
2 #define AMREX_IPARSER_H_
3 
4 #include <AMReX_Arena.H>
5 #include <AMReX_Array.H>
6 #include <AMReX_GpuDevice.H>
7 #include <AMReX_IParser_Exe.H>
8 #include <AMReX_Vector.H>
9 
10 #include <memory>
11 #include <string>
12 #include <set>
13 
14 namespace amrex {
15 
16 template <int N>
18 {
19  template <int M=N, std::enable_if_t<M==0,int> = 0>
21  long long operator() () const noexcept
22  {
25  }
26 
27  template <typename... Ts>
29  std::enable_if_t<sizeof...(Ts) == N && std::conjunction_v<std::is_integral<Ts>...>,
30  long long>
31  operator() (Ts... var) const noexcept
32  {
33  amrex::GpuArray<long long,N> l_var{var...};
34  AMREX_IF_ON_DEVICE((return iparser_exe_eval(m_device_executor, l_var.data());))
35  AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, l_var.data());))
36  }
37 
39  long long operator() (GpuArray<long long, N> const& var) const noexcept
40  {
42  AMREX_IF_ON_HOST((return iparser_exe_eval(m_host_executor, var.data());))
43  }
44 
46  explicit operator bool () const {
47  AMREX_IF_ON_DEVICE((return m_device_executor != nullptr;))
48  AMREX_IF_ON_HOST((return m_host_executor != nullptr;))
49  }
50 
51  char* m_host_executor = nullptr;
52 #ifdef AMREX_USE_GPU
53  char* m_device_executor = nullptr;
54 #endif
55 };
56 
57 class IParser
58 {
59 public:
60  IParser (std::string const& func_body);
61  IParser () = default;
62  void define (std::string const& func_body);
63 
64  explicit operator bool () const;
65 
66  void setConstant (std::string const& name, long long c);
67 
68  void registerVariables (Vector<std::string> const& vars);
69 
70  void print () const;
71 
72  [[nodiscard]] int depth () const;
73  [[nodiscard]] int maxStackSize () const;
74 
75  [[nodiscard]] std::string expr () const;
76 
77  [[nodiscard]] std::set<std::string> symbols () const;
78 
80  template <int N> [[nodiscard]] IParserExecutor<N> compile () const;
81 
83  template <int N> [[nodiscard]] IParserExecutor<N> compileHost () const;
84 
85 private:
86 
87  struct Data {
88  std::string m_expression;
89  struct amrex_iparser* m_iparser = nullptr;
90  int m_nvars = 0;
91  mutable char* m_host_executor = nullptr;
92 #ifdef AMREX_USE_GPU
93  mutable char* m_device_executor = nullptr;
94 #endif
95  mutable int m_max_stack_size = 0;
96  mutable int m_exe_size = 0;
97  Data () = default;
98  ~Data ();
99  Data (Data const&) = delete;
100  Data (Data &&) = delete;
101  Data& operator= (Data const&) = delete;
102  Data& operator= (Data &&) = delete;
103  };
104 
105  std::shared_ptr<Data> m_data;
106 };
107 
108 template <int N>
111 {
112  if (m_data && m_data->m_iparser) {
113  AMREX_ASSERT(N == m_data->m_nvars);
114 
115  if (!(m_data->m_host_executor)) {
116  int stack_size;
117  m_data->m_exe_size = static_cast<int>
118  (iparser_exe_size(m_data->m_iparser, m_data->m_max_stack_size,
119  stack_size));
120 
121  if (m_data->m_max_stack_size > AMREX_IPARSER_STACK_SIZE) {
122  amrex::Abort("amrex::IParser: AMREX_IPARSER_STACK_SIZE, "
123  + std::to_string(AMREX_IPARSER_STACK_SIZE) + ", is too small for "
124  + m_data->m_expression);
125  }
126  if (stack_size != 0) {
127  amrex::Abort("amrex::IParser: something went wrong with iparser stack! "
128  + std::to_string(stack_size));
129  }
130 
131  m_data->m_host_executor = (char*)The_Pinned_Arena()->alloc(m_data->m_exe_size);
132 
133  try {
134  iparser_compile(m_data->m_iparser, m_data->m_host_executor);
135  } catch (const std::runtime_error& e) {
136  throw std::runtime_error(std::string(e.what()) + " in IParser expression \""
137  + m_data->m_expression + "\"");
138  }
139  }
140 
141 #ifdef AMREX_USE_GPU
142  return IParserExecutor<N>{m_data->m_host_executor, m_data->m_device_executor};
143 #else
144  return IParserExecutor<N>{m_data->m_host_executor};
145 #endif
146  } else {
147  return IParserExecutor<N>{};
148  }
149 }
150 
151 template <int N>
154 {
155  auto exe = compileHost<N>();
156 
157 #ifdef AMREX_USE_GPU
158  if (m_data && m_data->m_iparser && !(m_data->m_device_executor)) {
159  m_data->m_device_executor = (char*)The_Arena()->alloc(m_data->m_exe_size);
160  Gpu::htod_memcpy_async(m_data->m_device_executor, m_data->m_host_executor,
161  m_data->m_exe_size);
163  exe.m_device_executor = m_data->m_device_executor;
164  }
165 #endif
166 
167  return exe;
168 }
169 
170 }
171 
172 #endif
#define AMREX_ASSERT(EX)
Definition: AMReX_BLassert.H:38
#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
#define AMREX_IPARSER_STACK_SIZE
Definition: AMReX_IParser_Exe.H:12
virtual void * alloc(std::size_t sz)=0
Definition: AMReX_IParser.H:58
void print() const
Definition: AMReX_IParser.cpp:76
std::set< std::string > symbols() const
Definition: AMReX_IParser.cpp:114
void setConstant(std::string const &name, long long c)
Definition: AMReX_IParser.cpp:57
IParserExecutor< N > compileHost() const
This compiles for CPU only.
Definition: AMReX_IParser.H:110
std::string expr() const
Definition: AMReX_IParser.cpp:104
IParserExecutor< N > compile() const
This compiles for both GPU and CPU.
Definition: AMReX_IParser.H:153
void registerVariables(Vector< std::string > const &vars)
Definition: AMReX_IParser.cpp:65
int depth() const
Definition: AMReX_IParser.cpp:84
void define(std::string const &func_body)
Definition: AMReX_IParser.cpp:18
std::shared_ptr< Data > m_data
Definition: AMReX_IParser.H:105
IParser()=default
int maxStackSize() const
Definition: AMReX_IParser.cpp:94
void streamSynchronize() noexcept
Definition: AMReX_GpuDevice.H:237
void htod_memcpy_async(void *p_d, const void *p_h, const std::size_t sz) noexcept
Definition: AMReX_GpuDevice.H:251
Definition: AMReX_Amr.cpp:49
void iparser_compile(struct amrex_iparser *parser, char *p)
Definition: AMReX_IParser_Exe.H:515
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE long long iparser_exe_eval(const char *p, long long const *x)
Definition: AMReX_IParser_Exe.H:231
Arena * The_Pinned_Arena()
Definition: AMReX_Arena.cpp:634
void Abort(const std::string &msg)
Print out message to cerr and exit via abort().
Definition: AMReX.cpp:221
Arena * The_Arena()
Definition: AMReX_Arena.cpp:594
std::size_t iparser_exe_size(struct amrex_iparser *parser, int &max_stack_size, int &stack_size)
Definition: AMReX_IParser_Exe.H:502
Definition: AMReX_Array.H:33
Definition: AMReX_IParser.H:18
char * m_device_executor
Definition: AMReX_IParser.H:53
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE long long operator()() const noexcept
Definition: AMReX_IParser.H:21
char * m_host_executor
Definition: AMReX_IParser.H:51
Definition: AMReX_IParser.H:87
int m_exe_size
Definition: AMReX_IParser.H:96
Data(Data &&)=delete
~Data()
Definition: AMReX_IParser.cpp:41
int m_max_stack_size
Definition: AMReX_IParser.H:95
int m_nvars
Definition: AMReX_IParser.H:90
char * m_device_executor
Definition: AMReX_IParser.H:93
std::string m_expression
Definition: AMReX_IParser.H:88
char * m_host_executor
Definition: AMReX_IParser.H:91
Data(Data const &)=delete
struct amrex_iparser * m_iparser
Definition: AMReX_IParser.H:89
Data & operator=(Data const &)=delete
Definition: AMReX_IParser_Y.H:153