Virtual Testbed
Ship dynamics simulator for extreme conditions
wetted_surface_solver_opencl.cc
1 #include <vtestbed/config/opencl.hh>
2 #include <vtestbed/config/real_type.hh>
3 #include <vtestbed/core/policy.hh>
4 #include <vtestbed/core/ship.hh>
5 #include <vtestbed/core/ship_hull_panel.hh>
6 #include <vtestbed/core/wetted_surface_solver.hh>
7 #include <vtestbed/geometry/face.hh>
8 #include <vtestbed/opencl/opencl.hh>
9 #include <vtestbed/opencl/vector.hh>
10 
11 //#define VTB_DEBUG_WETTED_PANELS_OPENCL
12 
16 using vtb::opencl::make_vector;
17 
18 namespace vtb {
19 
20  namespace core {
21 
22  template <class T, int N>
24  public Wetted_surface_solver<T,N>,
25  public Context_base {
26 
27  private:
29  using typename base_type::ship_type;
30  using typename base_type::grid_type;
31  using typename base_type::panel_type;
32  using typename base_type::waterline_type;
33  using typename base_type::vertex_type;
34  //using vertex_type = vtb::geometry::Vertex<T,N>;
35  using line_segment_type = typename waterline_type::value_type;
37 
38  private:
39  Buffer<vertex_type> _d_vertices;
40  Buffer<face_type> _d_faces;
41  Buffer<line_segment_type> _d_waterline;
42  clx::kernel _kernel_regular, _kernel_irregular;
43 
44  public:
45 
46  using Context_base::context;
47 
48  void context(Context* rhs) override {
49  Context_base::context(rhs);
50  auto cc = context()->compiler();
51  auto options = cc.options();
52  cc.options(options + " -DVTB_REGULAR");
53  this->_kernel_regular =
54  cc.compile("wetted_surface.cl").kernel("wetted_panels");
55  cc.options(options + " -DVTB_IRREGULAR");
56  this->_kernel_irregular =
57  cc.compile("wetted_surface.cl").kernel("wetted_panels");
58  }
59 
60  void
61  solve(
62  const ship_type& ship,
63  const grid_type& grid_txyz,
64  Array3<T> wavy_surface
65  ) override;
66 
67  void
68  solve(
69  const ship_type& ship,
70  const grid_type& grid_txyz,
71  Array3<vertex_type> wavy_surface
72  ) override;
73 
74  private:
75 
76  void
77  do_solve(const ship_type& ship,
78  const grid_type& grid_txyz,
79  const void* wavy_surface,
80  size_t wavy_surface_size,
81  clx::kernel& kernel);
82 
83  };
84 
85  }
86 
87 }
88 template <class T, int N>
89 void
91  const ship_type& ship,
92  const grid_type& grid_txyz,
93  const void* wavy_surface,
94  size_t wavy_surface_size,
95  clx::kernel& kernel
96 ) {
97  const auto& vertices = ship.hull().vertices();
98  const auto& faces = ship.hull().faces();
99  const int nvertices = vertices.size();
100  const int nfaces = faces.size();
101  auto& waterline = this->_waterline;
102  auto& all_panels = this->_all_panels;
103  auto& mask = this->_wetted_vertices_mask;
104  mask.resize(nvertices);
105  mask.assign(nvertices, false);
106  all_panels.resize(nfaces);
107  waterline.resize(nfaces);
108  Grid<T,2> grid_xy = grid_txyz.select(1,2);
109  #if defined(VTB_DEBUG_WETTED_PANELS_OPENCL)
110  std::clog << "wavy surface size: " << grid_xy << std::endl;
111  #endif
112  int offset = (grid_txyz.extent(0)-1)*product(grid_xy.shape());
113  Buffer<panel_type> d_panels;
114  clx::buffer d_wavy_surface;
115  auto& ppl = this->context()->pipeline();
116  ppl.allocate(all_panels, d_panels);
117  ppl.allocate(waterline, this->_d_waterline);
118  ppl.copy(vertices, this->_d_vertices);
119  ppl.copy(faces, this->_d_faces);
120  ppl.copy(wavy_surface, wavy_surface_size, d_wavy_surface);
121  kernel.argument(0, nfaces);
122  kernel.argument(1, this->_d_faces);
123  kernel.argument(2, this->_d_vertices);
124  kernel.argument(3, d_panels);
125  kernel.argument(4, make_vector(ship.position()));
126  kernel.argument(5, make_vector(ship.rotation_matrix()));
127  kernel.argument(6, d_wavy_surface);
128  kernel.argument(7, offset);
129  kernel.argument(8, make_vector(grid_xy.lbound()));
130  kernel.argument(9, make_vector(grid_xy.ubound()));
131  kernel.argument(10, make_vector(grid_xy.shape()));
132  kernel.argument(11, this->_d_waterline);
133  ppl.step();
134  ppl.kernel(kernel, clx::range(nfaces));
135  ppl.step();
136  ppl.copy(d_panels, all_panels);
137  ppl.copy(this->_d_waterline, waterline);
138  ppl.wait();
139  auto& dry_panels = this->_dry_panels;
140  dry_panels.clear();
141  dry_panels.reserve(nfaces/2);
142  auto& wetted_panels = this->_wetted_panels;
143  wetted_panels.clear();
144  wetted_panels.reserve(nfaces/2);
145  for (int i=0; i<nfaces; ++i) {
146  const auto& panel = all_panels[i];
147  if (panel.wetted()) {
148  wetted_panels.emplace_back(panel);
149  const auto& f = faces[i];
150  mask[f[0]] = true, mask[f[1]] = true, mask[f[2]] = true;
151  } else {
152  dry_panels.emplace_back(panel);
153  }
154  }
155  int new_waterline_size = 0;
156  for (int i=0; i<nfaces; ++i) {
157  const auto& segment = waterline[i];
158  if (all(segment.front() == 0 && segment.back() == 0)) {
159  new_waterline_size = i;
160  break;
161  }
162  }
163  waterline.resize(new_waterline_size);
164 }
165 
166 template <class T, int N>
167 void
169  const ship_type& ship,
170  const grid_type& grid_txyz,
171  Array3<vertex_type> wavy_surface
172 ) {
173  if (!wavy_surface.isStorageContiguous()) { wavy_surface.makeUnique(); }
174  do_solve(ship, grid_txyz, wavy_surface.data(), wavy_surface.size()*sizeof(vertex_type),
175  this->_kernel_irregular);
176 }
177 
178 template <class T, int N>
179 void
181  const ship_type& ship,
182  const grid_type& grid_txyz,
183  Array3<T> wavy_surface
184 ) {
185  if (!wavy_surface.isStorageContiguous()) { wavy_surface.makeUnique(); }
186  do_solve(ship, grid_txyz, wavy_surface.data(), wavy_surface.size()*sizeof(T),
187  this->_kernel_regular);
188 }
189 
190 template <>
191 auto
192 vtb::core::make_wetted_surface_solver<VTB_REAL_TYPE,3,vtb::core::Policy::OpenCL>() ->
196  );
197 }
198 
const vec3 & position(int i=0) const
Get position or its time derivatives in Earth-fixed coordinate system.
Definition: core/ship.hh:253
Rigid ship with a mass and translational and angular velocity.
Definition: core/ship.hh:186
const vec size() const noexcept
The size of the region.
Definition: core/grid.hh:224
Triangular ship hull panel (face).
Main namespace.
Definition: convert.hh:9
void solve(const ship_type &ship, const grid_type &grid_txyz, Array3< T > wavy_surface) override
Determine underwater hull panels (faces) taking into account ship position and orientation.