6 #include <vtestbed/config/opencl.hh> 7 #include <vtestbed/config/openmp.hh> 8 #include <vtestbed/config/real_type.hh> 9 #include <vtestbed/core/anlt_wind_solver.hh> 10 #include <vtestbed/core/arma_wind_solver.hh> 11 #include <vtestbed/core/cosine_wave.hh> 12 #include <vtestbed/core/propulsor.hh> 13 #include <vtestbed/core/ship_motion_solver.hh> 14 #include <vtestbed/core/stokes_wave.hh> 15 #include <vtestbed/core/testbed.hh> 16 #include <vtestbed/core/wetted_surface_solver.hh> 17 #include <vtestbed/geometry/basis.hh> 18 #include <vtestbed/profile/profile.hh> 20 #if defined(VTB_WITH_OPENCL) 21 #include <vtestbed/opencl/opencl.hh> 26 sizeof(vtb::core::Vector3<VTB_REAL_TYPE>)*4,
30 template <
class T,
int N>
33 {T{-1}, T(-100), T(-100), T{-100}},
34 {T{0}, T(100), T(100), T{2}},
42 this->_wpdomain_xyz.lbound() = 0;
43 this->_wpdomain_xyz.ubound() = 0;
44 grid3 wsgrid{this->wavy_surface_grid()};
45 this->_wavysurface.resize(wsgrid.shape());
46 this->_wavysurface = 0;
47 this->_irregular_wavysurface.resize(wsgrid.shape());
50 [&] (
const blitz::TinyVector<int,N>& idx) {
51 auto txy = wsgrid(idx);
52 this->_irregular_wavysurface(idx) = {txy(1), txy(2), 0};
55 grid4 vpgrid{this->_grid_txyz.select(0,3,1,2)};
56 this->_vpotential.resize(vpgrid.shape());
57 this->_statistics_log.open(
"statistics.log");
58 this->_statistics.write_header(this->_statistics_log);
61 this->_ship_motion_solver.reset(
new ship_motion_solver_type);
64 template <
class T,
int N>
67 VTB_PROFILE_BLOCK(
"step");
68 const T t0 = this->_grid_txyz.ubound(0);
69 this->_grid_txyz.lbound(0) = t0;
70 this->_grid_txyz.ubound(0) = t0 + dt;
71 switch (this->get_solver_type()) {
72 case Solver_type::regular_solver: this->step_regular();
break;
73 case Solver_type::gerstner_solver: this->step_irregular();
break;
84 this->record_statistics(this->_statistics);
87 template <
class T,
int N>
90 this->generate_waves();
91 this->compute_wetted_panels_regular();
92 if (has_wetted_panels()) {
93 this->clamp_grid_to_wetted_panels();
94 if (has_wave_pressure_domain()) {
95 this->compute_wave_numbers();
96 this->compute_velocity_potential();
97 this->compute_wave_pressure();
102 template <
class T,
int N>
106 VTB_PROFILE_BLOCK(
"fluid_motion");
107 this->_gerstner_solver->compute_positions(this->_ship, this->_wssolver->all_panels(),
108 this->_grid_txyz.select(0,1,2), this->_irregular_wavysurface);
110 this->compute_wetted_panels_irregular();
111 if (has_wetted_panels()) {
112 this->clamp_grid_to_wetted_panels();
113 if (has_wave_pressure_domain()) {
114 VTB_PROFILE_BLOCK(
"compute_forces");
117 this->_gerstner_solver->compute_forces(
119 this->_grid_txyz.select(0,3,1,2),
120 this->_wssolver->wetted_panels());
121 this->_water_velocity.reference(this->_gerstner_solver->velocity());
126 template <
class T,
int N>
129 this->_grid_txyz.lbound(0) = -1;
130 this->_grid_txyz.ubound(0) = 0;
132 this->_statistics.clear();
133 this->_statistics_log.close();
134 this->_statistics_log.open(
"statistics.log");
135 this->_wavysurface = 0;
136 this->_vpotential = 0;
137 this->_wind_field = T{};
138 this->_irregular_wavysurface = T{};
141 template <
class T,
int N>
144 VTB_PROFILE_BLOCK(
"waves");
145 grid3 wsgrid{this->wavy_surface_grid()};
146 this->_wavysurface.reference(this->_wsgenerator->generate(wsgrid));
149 template <
class T,
int N>
152 VTB_PROFILE_BLOCK(
"wind");
153 this->_anlt_wind_solver->step(this->_wind_grid, this->_wssolver->dry_panels());
154 this->_wind_field.reference(this->_anlt_wind_solver->wind_field());
157 template <
class T,
int N>
160 VTB_PROFILE_BLOCK(
"wetted_panels");
161 this->_wssolver->solve(ship(), grid_txyz(), this->wavy_surface());
164 template <
class T,
int N>
167 VTB_PROFILE_BLOCK(
"wetted_panels");
168 this->_wssolver->solve(ship(), grid_txyz(), this->irregular_wavy_surface());
171 template <
class T,
int N>
175 const auto& wetted_panels = this->_wssolver->wetted_panels();
177 for (
const auto& panel : wetted_panels) {
178 const auto& centre = panel.centre();
179 mm[0].update(centre(0));
180 mm[1].update(centre(1));
181 mm[2].update(centre(2));
183 vec3 x_min{mm[0].min(),mm[1].min(),mm[2].min()};
184 vec3 x_max{mm[0].max(),mm[1].max(),mm[2].max()};
186 if (!wetted_panels.empty()) {
187 T z_max = std::min(x_max(2), blitz::max(this->_wavysurface)) + 1;
189 this->_grid_txyz.ubound(3) = z_max;
190 this->_grid_txyz.lbound(3) = std::min(x_min(2)-1, z_max);
192 grid3 grid_xyz{this->_grid_txyz.select(1,2,3)};
193 x_min = clamp(x_min, grid_xyz);
194 x_max = clamp(x_max, grid_xyz);
195 int3 idx_min = int3{blitz::floor(grid_xyz.index(x_min))};
196 int3 idx_max = int3{blitz::ceil(grid_xyz.index(x_max))};
197 idx_min = blitz::max(0, idx_min);
198 idx_max = blitz::min(grid_xyz.shape()-1, idx_max);
200 int3 extent = idx_max - idx_min + 1;
201 if (blitz::all(extent > 0)) {
202 for (
int i=0; i<2; ++i) {
204 if (!blitz::is_power_of_two(e)) {
205 extent(i) = blitz::next_power_of_two(e);
208 idx_max = idx_min + extent - 1;
209 for (
int i=0; i<2; ++i) {
210 int diff = idx_max(i) - (grid_xyz.extent(i) - 1);
216 if (blitz::any(idx_min < 0)) {
218 <<
"Please, increase wavy surface size to speed-up Fourier transforms" 221 extent = idx_max - idx_min + 1;
223 domain3 d{idx_min, idx_max};
224 this->_wpdomain_xyz = d;
227 template <
class T,
int N>
230 const auto& _ = blitz::Range::all();
231 const auto& grid_xy = this->_grid_txyz.select(1,2);
232 const auto& zeta = this->_wavysurface;
233 const int slice_t = zeta.extent(0)-1;
234 const auto& w = wave_statistics(zeta(slice_t,_,_), grid_xy);
235 auto& waves = this->_statistics.waves();
240 template <
class T,
int N>
243 return wave_number_grid(this->_statistics.waves()).select(1,2);
246 template <
class T,
int N>
249 VTB_PROFILE_BLOCK(
"wave_velocity");
250 const auto _ = blitz::Range::all();
251 _vpgrid_tzxy = _grid_txyz.select(0,3,1,2);
252 _vpgrid_tzxy = _vpgrid_tzxy(_,_wpdomain_xyz[2],_wpdomain_xyz[0],_wpdomain_xyz[1]);
253 _vpotential.resize(_vpgrid_tzxy.shape());
254 _vpsolver->wave_number_grid(this->wave_number_grid_2d());
257 _wavysurface(_,_wpdomain_xyz[0],_wpdomain_xyz[1]),
262 template <
class T,
int N>
265 VTB_PROFILE_BLOCK(
"wave_pressure");
266 grid3 wsgrid{_vpgrid_tzxy.select(0,2,3)};
267 this->_wpsolver->solve(
272 this->_wssolver->wetted_panels()
276 template <
class T,
int N>
279 VTB_PROFILE_BLOCK(
"ship_motions");
280 const T t0 = this->_grid_txyz.lbound(0);
281 const T t1 = this->_grid_txyz.ubound(0);
282 this->_ship_motion_solver->solve(
284 this->wetted_panels(),
292 template <
class T,
int N>
295 using Record =
typename statistics_type::Record;
296 VTB_PROFILE_BLOCK(
"statistics");
297 T t = this->_grid_txyz.ubound(0);
298 const auto& ship = this->_ship;
299 stats.record(Record::Time, t);
300 stats.record(Record::Euler_angles, ship.euler_angles());
301 stats.record(Record::Position, ship.position());
302 stats.record(Record::Velocity, ship.velocity());
303 stats.record(Record::Angular_velocity, vector_to(ship.rotation_matrix(), ship.angular_velocity()));
304 stats.record(Record::Acceleration, vector_to(ship.rotation_matrix(), ship.acceleration()));
305 stats.record(Record::Angular_acceleration, ship.angular_acceleration());
306 stats.record(Record::Underwater_volume,
307 this->_ship_motion_solver->equation().displacement());
308 stats.record(Record::Angular_momentum, ship.angular_momentum());
309 const auto& zeta = this->_wavysurface;
310 const auto nx = zeta.extent(1);
311 const auto ny = zeta.extent(2);
312 stats.record(Record::Wavy_surface, zeta(zeta.extent(0)-1,nx/2,ny/2));
313 stats.record_waves();
314 stats.write_back(this->_statistics_log);
315 this->_statistics_log.flush();
318 template <
class T,
int N>
321 #if defined(VTB_WITH_OPENMP) 322 auto solver_t = get_solver_type();
323 this->velocity_potential_solver(make_velocity_potential_solver<T,3,Policy::OpenMP>());
324 this->wave_pressure_solver(make_wave_pressure_solver<T,Policy::OpenMP>());
325 this->wetted_surface_solver(make_wetted_surface_solver<T,3,Policy::OpenMP>());
326 this->anlt_wind_solver(make_anlt_wind_solver<T,Policy::OpenMP>());
327 using default_wave = Propagating_stokes_wave<T,3>;
328 this->wavy_surface_generator(
329 make_plain_wave_generator<T,3,default_wave,Policy::OpenMP>()
331 this->gerstner_solver(make_gerstner_solver<T,3,Policy::OpenMP>());
332 set_solver_type(solver_t);
336 template <
class T,
int N>
339 #if defined(VTB_WITH_OPENCL) 340 auto solver_t = get_solver_type();
341 this->velocity_potential_solver(make_velocity_potential_solver<T,3,Policy::OpenCL>());
342 this->wave_pressure_solver(make_wave_pressure_solver<T,Policy::OpenCL>());
343 this->wetted_surface_solver(make_wetted_surface_solver<T,3,Policy::OpenCL>());
344 this->anlt_wind_solver(make_anlt_wind_solver<T,Policy::OpenCL>());
345 using default_wave = Propagating_stokes_wave<T,3>;
346 this->wavy_surface_generator(
347 make_plain_wave_generator<T,3,default_wave,Policy::OpenCL>()
349 this->gerstner_solver(make_gerstner_solver<T,3,Policy::OpenCL>());
350 set_solver_type(solver_t);
354 template <
class T,
int N>
357 #if defined(VTB_WITH_OPENCL) 359 auto context = reinterpret_cast<Context*>(ptr);
360 if (
auto vpsolver = dynamic_cast<Context_base*>(this->_vpsolver.get())) {
361 vpsolver->context(context);
363 if (
auto wpsolver = dynamic_cast<Context_base*>(this->_wpsolver.get())) {
364 wpsolver->context(context);
366 if (
auto wssolver = dynamic_cast<Context_base*>(this->_wssolver.get())) {
367 wssolver->context(context);
369 if (
auto wsgenerator = dynamic_cast<Context_base*>(this->_wsgenerator.get())) {
370 wsgenerator->context(context);
372 if (
auto gerstner_solver = dynamic_cast<Context_base*>(this->_gerstner_solver.get())) {
373 gerstner_solver->context(context);
375 if (
auto wind_solver = dynamic_cast<Context_base*>(this->_anlt_wind_solver.get())) {
376 wind_solver->context(context);
Triangular ship hull panel (face).
Main class for interacting with virtual testbed.
void reset()
Reset simulation to the initial state and retain solver configuration.