Virtual Testbed
Ship dynamics simulator for extreme conditions
wave_pressure_opencl.cc
1 #include <vtestbed/base/constants.hh>
2 #include <vtestbed/config/real_type.hh>
3 #include <vtestbed/core/wave_pressure.hh>
4 #include <vtestbed/opencl/derivative.hh>
5 #include <vtestbed/opencl/opencl.hh>
6 #include <vtestbed/opencl/pipeline.hh>
7 #include <vtestbed/opencl/vector.hh>
8 
9 using vtb::core::Policy;
14 using vtb::opencl::make_vector;
15 
16 namespace vtb {
17 
18  namespace core {
19 
20  template <class T>
22  public Wave_pressure_solver<T>,
23  public Context_base {
24 
25  private:
27 
28  public:
29  using typename base_type::panel_type;
30  using typename base_type::panel_array;
31  using typename base_type::grid3;
32  using typename base_type::grid4;
33  using typename base_type::array3;
34  using typename base_type::array4;
35  using typename base_type::vec3;
37 
38  private:
39  derivative_type _derivative;
40  Buffer<T> _d_derivative_phi[4];
41  clx::kernel _calculate_pressure, _calculate_pressure_force;
42 
43  public:
44 
45  void
46  calculate_pressure(
47  const grid4& grid,
48  const array4& velocity_potential,
49  const array3& wavy_surface,
50  Buffer<T>& pressure
51  );
52 
53  void
54  calculate_pressure_force(
55  const grid4& pressure_grid,
56  Buffer<T>& pressure,
57  panel_array& panels
58  );
59 
60  void solve(const grid3& wavy_surface_grid,
61  array3 wavy_surface,
62  const grid4& phi_grid,
63  array4 velocity_potential,
64  panel_array& panels) override;
65 
66  using Context_base::context;
67 
68  void context(Context* rhs) override {
69  Context_base::context(rhs);
70  auto prog = context()->compiler().compile("wave_pressure.cl");
71  this->_calculate_pressure = prog.kernel("calculate_pressure");
72  this->_calculate_pressure_force = prog.kernel("calculate_pressure_force");
73  this->_derivative.context(rhs);
74  }
75 
76  };
77 
78  }
79 
80 }
81 
82 template <class T>
83 void
85  const grid3& wavy_surface_grid,
86  array3 wavy_surface,
87  const grid4& phi_grid,
88  array4 velocity_potential,
89  panel_array& panels
90 ) {
91  using blitz::Range;
92  using blitz::RectDomain;
93  grid3 grid_xyz = phi_grid.select(2,3,1);
94  if (this->clip()) {
95  grid_xyz = clamp(grid_xyz, panels);
96  if (grid_xyz.empty()) { return; }
97  grid_xyz.compact();
98  }
99  RectDomain<3> rect{grid_xyz.begin(), grid_xyz.end()-1};
100  const auto& _ = Range::all();
101  const grid4& smaller_grid = phi_grid(_,rect[2],rect[0],rect[1]);
102  Array<T,4> phi(velocity_potential(_,rect[2],rect[0],rect[1]));
103  Buffer<T> pressure;
104  this->calculate_pressure(smaller_grid, phi, wavy_surface, pressure);
105  this->calculate_pressure_force(smaller_grid, pressure, panels);
106 }
107 
108 template <class T>
109 void
112  const grid4& grid,
113  const array4& phi,
114  const array3& wavy_surface,
115  Buffer<T>& d_pressure
116 ) {
117  using vtb::core::int1;
118  using vtb::base::constants;
119  const auto& shape = grid.shape();
120  const size_t pressure_size = product(shape);
121  auto context = this->context();
122  auto& ppl = context->pipeline();
123  Buffer<T> d_phi;
124  ppl.copy(phi, d_phi);
125  ppl.step();
126  auto& d_derivative_phi = this->_d_derivative_phi;
127  for (int i=0; i<4; ++i) {
128  this->_derivative.solve(d_phi, grid, 0, d_derivative_phi[i]);
129  }
130  auto& kernel = this->_calculate_pressure;
131  Buffer<T> d_wavy_surface;
132  ppl.copy(wavy_surface, d_wavy_surface);
133  ppl.allocate(pressure_size, d_pressure);
134  kernel.arguments(
135  d_derivative_phi[0], d_derivative_phi[1], d_derivative_phi[2], d_derivative_phi[3],
136  d_wavy_surface,
137  grid.lbound(1), grid.delta(1),
138  shape(1), shape(2), shape(3),
139  d_pressure);
140  ppl.step();
141  ppl.kernel(kernel, clx::range{pressure_size});
142  ppl.step();
143 }
144 
145 template <class T>
146 void
148  const grid4& pressure_grid,
149  Buffer<T>& d_pressure,
150  panel_array& panels
151 ) {
152  auto context = this->context();
153  const auto& new_pressure_grid = pressure_grid.select(1,2,3);
154  Buffer<panel_type> d_panels;
155  auto& ppl = context->pipeline();
156  ppl.copy(panels, d_panels);
157  auto& kernel = this->_calculate_pressure_force;
158  int offset = (pressure_grid.extent(0)-1)*product(new_pressure_grid.shape());
159  kernel.argument(0, make_vector(new_pressure_grid.lbound()));
160  kernel.argument(1, make_vector(new_pressure_grid.ubound()));
161  kernel.argument(2, d_pressure);
162  kernel.argument(3, offset);
163  kernel.argument(4, make_vector(new_pressure_grid.shape()));
164  kernel.argument(5, d_panels);
165  ppl.step();
166  ppl.kernel(kernel, clx::range(panels.size()));
167  ppl.step();
168  ppl.copy(d_panels, panels);
169  ppl.wait();
170 }
171 
172 template <>
173 auto
174 vtb::core::make_wave_pressure_solver<VTB_REAL_TYPE,Policy::OpenCL>()
177  new Wave_pressure_solver_opencl<VTB_REAL_TYPE>
178  );
179 }
Base class for all wave pressure solvers.
Triangular ship hull panel (face).
Main namespace.
Definition: convert.hh:9