Virtual Testbed
Ship dynamics simulator for extreme conditions
plain_wave_generator_opencl.cc
1 #include <vtestbed/config/real_type.hh>
2 #include <vtestbed/core/cosine_wave.hh>
3 #include <vtestbed/core/stokes_wave.hh>
4 #include <vtestbed/core/plain_wave_generator.hh>
5 #include <vtestbed/opencl/opencl.hh>
6 #include <vtestbed/opencl/vector.hh>
7 
8 using namespace vtb::opencl;
9 
10 namespace {
11 
12  template <class T> struct Function_name;
13 
14  template <class T,int N>
15  struct Function_name<vtb::core::Propagating_cosine_wave<T,N>> {
16  static constexpr const char* value = "propagating_cosine_wave";
17  };
18 
19  template <class T,int N>
20  struct Function_name<vtb::core::Standing_cosine_wave<T,N>> {
21  static constexpr const char* value = "standing_cosine_wave";
22  };
23 
24  template <class T,int N>
25  struct Function_name<vtb::core::Propagating_stokes_wave<T,N>> {
26  static constexpr const char* value = "propagating_stokes_wave";
27  };
28 
29 }
30 
31 namespace vtb {
32 
33  namespace core {
34 
35  template <class T, int N, class Wave>
37  public Plain_wave_generator<T,N,Wave,Policy::OpenCL>,
38  public Context_base {
39 
40  private:
42  using typename base_type::grid_type;
43  using typename base_type::array_type;
44 
45  private:
46  clx::kernel _kernel;
47  clx::buffer _d_surface;
48 
49  public:
51 
52  void generate(const grid_type& grid, array_type& result) override {
53  using vtb::opencl::resize;
54  auto context = this->context();
55  auto& ppl = context->pipeline();
56  auto& kernel = this->_kernel;
57  resize<T>(context->context(), this->_d_surface, result.size());
58  kernel.argument(0, this->wave());
59  kernel.argument(1, make_vector(grid.lbound()));
60  kernel.argument(2, make_vector(grid.delta()));
61  kernel.argument(3, make_vector(grid.shape()));
62  kernel.argument(4, this->_d_surface);
63  ppl.kernel(kernel, grid.shape());
64  ppl.step();
65  ppl.copy(this->_d_surface.slice(0,result.size()*sizeof(T)), result.data());
66  ppl.wait();
67  }
68 
69  using Context_base::context;
70 
71  void context(Context* rhs) override {
72  Context_base::context(rhs);
73  auto cc = context()->compiler_copy();
75  auto options = cc.options();
76  std::string old_flags = real_type_flags();
77  auto pos = options.find(old_flags);
78  if (pos != std::string::npos) {
79  options.erase(pos, old_flags.size());
80  options += real_type_flags<T>();
81  cc.options(options);
82  }
83  }
84  auto prog = cc.compile("plain_wave_generator.cl");
85  this->_kernel = prog.kernel(Function_name<Wave>::value);
86  };
87 
88  };
89 
90  template <class T, int N>
92  make_plain_wave_generator_opencl(std::any wave);
93 
94  }
95 
96 }
97 
98 #define VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(T,N,Wave) \
99 template <> \
100 auto \
101 vtb::core::make_plain_wave_generator(const Wave<T,N>& wave) \
102 -> std::unique_ptr<Plain_wave_generator<T,N,Wave<T,N>,Policy::OpenCL>> { \
103  return std::unique_ptr<Plain_wave_generator<T,N,Wave<T,N>,Policy::OpenCL>>( \
104  new Plain_wave_generator_opencl<T,N,Wave<T,N>>(wave) \
105  ); \
106 } \
107 template <> \
108 auto \
109 vtb::core::make_plain_wave_generator() \
110 -> std::unique_ptr<Plain_wave_generator<T,N,Wave<T,N>,Policy::OpenCL>> { \
111  return std::unique_ptr<Plain_wave_generator<T,N,Wave<T,N>,Policy::OpenCL>>( \
112  new Plain_wave_generator_opencl<T,N,Wave<T,N>>() \
113  ); \
114 }
115 
116 VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(VTB_REAL_TYPE,3,Propagating_cosine_wave);
117 VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(VTB_REAL_TYPE,3,Standing_cosine_wave);
118 VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(VTB_REAL_TYPE,3,Propagating_stokes_wave);
119 #if defined(VTB_REAL_TYPE_FLOAT)
120 VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(double,3,Propagating_cosine_wave);
121 VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(double,3,Standing_cosine_wave);
122 VTB_MAKE_PLAIN_WAVE_SURFACE_GENERATOR(double,3,Propagating_stokes_wave);
123 #endif
124 
125 template <class T, int N>
127 vtb::core::make_plain_wave_generator_opencl(std::any wave) {
129  using propagating_cosine = Propagating_cosine_wave<T,N>;
130  using standing_cosine = Standing_cosine_wave<T,N>;
131  using propagating_stokes = Propagating_stokes_wave<T,N>;
132  if (wave.type() == typeid(propagating_cosine)) {
133  return pointer(new Plain_wave_generator_opencl<T,N,propagating_cosine>(
134  std::any_cast<propagating_cosine>(wave)));
135  }
136  if (wave.type() == typeid(standing_cosine)) {
137  return pointer(new Plain_wave_generator_opencl<T,N,standing_cosine>(
138  std::any_cast<standing_cosine>(wave)));
139  }
140  if (wave.type() == typeid(propagating_stokes)) {
141  return pointer(new Plain_wave_generator_opencl<T,N,propagating_stokes>(
142  std::any_cast<propagating_stokes>(wave)));
143  }
144  throw std::invalid_argument("bad wave");
145 }
146 
148 vtb::core::make_plain_wave_generator_opencl<VTB_REAL_TYPE,3>(std::any wave);
149 #if defined(VTB_REAL_TYPE_FLOAT)
151 vtb::core::make_plain_wave_generator_opencl<double,3>(std::any wave);
152 #endif
Propagating plain wave which has cosine shape.
Definition: cosine_wave.hh:17
Propagating third-order Stokes wave.
Definition: stokes_wave.hh:33
const vec & lbound() const noexcept
Lower bound of the region.
Definition: core/grid.hh:168
const int_n shape() const noexcept
The number of points for all dimensions.
Definition: core/grid.hh:108
const T delta(int i) const
The size of the patch (interval) for dimension i.
Definition: core/grid.hh:239
A region defined by start and end index and lower and upper bound for each dimension.
Definition: core/grid.hh:25
Wavy surface generator that produces elevation grid for individual wave.
Main namespace.
Definition: convert.hh:9
OpenCL glue code.
Standing plain wave which has cosine shape.
Definition: cosine_wave.hh:56
Base class for wavy surface generators.
Definition: core/types.hh:50