1 #include <vtestbed/base/constants.hh> 2 #include <vtestbed/base/for_loop.hh> 3 #include <vtestbed/config/openmp.hh> 4 #include <vtestbed/config/real_type.hh> 5 #include <vtestbed/core/gerstner.hh> 6 #include <vtestbed/core/grid_interpolation.hh> 7 #include <vtestbed/core/ship_hull_panel.hh> 8 #include <vtestbed/core/types.hh> 9 #include <vtestbed/geometry/linear_interpolation.hh> 20 using typename base_type::vertex_field_3d;
21 using typename base_type::scalar_field_3d;
24 using typename base_type::vertex_type;
31 enum class Quantity { Position, Velocity };
37 const grid4& grid_tzxy,
38 panel_array & wetted_panels
41 void compute_positions(
43 const panel_array& panels,
44 const grid3& grid_txy,
45 vertex_field_3d& result
49 const grid3& grid_xyz,
50 vertex_field_3d& result,
52 const panel_array& panels,
55 scalar_field_3d* potential=
nullptr 64 template <
class T>
void 67 const grid4& grid_tzxy,
68 panel_array & wetted_panels
70 int npanels = wetted_panels.size();
72 grid3 grid_zxy = grid_tzxy.select(1,2,3);
73 if (this->clip()) { grid_zxy = clamp(grid_zxy, wetted_panels); }
74 if (grid_zxy.ubound(2) > 0) { grid_zxy.ubound(2) = 0; }
75 if (grid_zxy.empty()) {
return; }
77 this->_velocity_grid_zxy = grid_zxy;
79 const T t = grid_tzxy.ubound(0);
80 auto& velocity = this->_velocity;
81 auto& potential = this->_potential;
82 velocity.resize(grid_zxy.shape());
83 potential.resize(grid_zxy.shape());
84 auto old_diffraction = this->diffraction();
85 this->diffraction(
false);
86 generate_field(grid_zxy, velocity, t, wetted_panels, ship,
87 Quantity::Velocity, &potential);
88 this->diffraction(old_diffraction);
90 Linear_function_irregular<T,vertex_type>
function(velocity, grid_zxy);
91 Grid_interpolation<T,3,Linear_function_irregular<T,vertex_type>,vertex_type>
92 interpolate(grid_zxy,
function);
96 #if defined(VTB_WITH_OPENMP) 97 #pragma omp parallel for 99 for (
int i=0; i<npanels; ++i) {
100 auto& panel = wetted_panels[i];
101 const auto& centre = panel.centre();
103 const auto& velocity = interpolate({centre(2),centre(0),centre(1)});
104 T pressure = p0 - rho*(T{0.5}*sum_of_squares(velocity) + g*z);
105 panel.force() = pressure * (-panel.normal()) * panel.area();
109 template <
class T>
void 111 const grid3& grid_zxy,
112 vertex_field_3d& result,
114 const panel_array& all_panels,
117 scalar_field_3d* potential
122 using vtb::geometry::unit;
123 using vec3 = Vector<T,3>;
126 constexpr
const C i(0,1);
127 const auto h = this->depth();
128 const bool infinite_depth = is_positive_infinity(h);
129 const bool diffraction = this->diffraction();
130 const bool radiation = this->radiation();
131 const bool waterline_only = this->waterline_only();
133 panels.reserve(all_panels.size());
134 for (
const auto& panel : all_panels) {
135 if ((waterline_only && panel.waterline()) || (!waterline_only && panel.wetted())) {
136 panels.emplace_back(panel);
139 parallel_for_loop<3>(
141 [&] (
const int3& idx) {
142 const auto& zxy = grid_zxy(idx);
143 const auto x = zxy(1), y = zxy(2), z = zxy(0);
144 vertex_type sum_position{x,y,z};
145 vertex_type sum_velocity{0,0,0};
147 for (
const auto& wave : this->_waves) {
148 const auto& _k_ = wave.wave_number();
149 T u = _k_(0), v = _k_(1);
151 T omega = wave.angular_frequency();
152 T ampl = wave.amplitude();
153 T exp1 = infinite_depth ? exp(k*z) : cosh(k*(z+h));
154 C exp2 = exp(i*(u*x + v*y - omega*t));
159 vec3 di(u,v,0), zeta(x,y,z);
161 for (
const auto& panel : panels) {
162 const auto& centre = panel.centre();
163 const auto& n = panel.normal();
164 vec3 ds = 2*dot(di,n)*n;
166 T weight = 1/(1+distance(zeta,centre));
168 exp3 += exp(i*(dot(dr,zeta) + dot(ds,centre)))*weight;
171 sum_weight += weight;
173 if (sum_weight != 0) {
174 exp3 /= sum_weight, sum_dr /= sum_weight;
176 w += exp1*exp3*exp(-i*omega*t);
178 vec3 sum_wave_vector{T{}};
184 for (
const auto& panel : panels) {
185 const auto& n = panel.normal();
186 const auto& centre = panel.centre();
189 auto old_velocity = velocity;
190 velocity = dot(velocity,n)*n;
192 T weight = 1/(1+length(vec3(zeta-centre)));
194 vec3 wave_vector = g / (length(velocity)) * n/2;
196 T omega = dot(wave_vector,velocity);
197 exp4 += exp(i*(dot(wave_vector,zeta) - omega*t))*weight;
198 sum_wave_vector += wave_vector;
199 sum_weight += weight;
201 if (sum_weight != 0) {
202 exp4 /= sum_weight, sum_wave_vector /= sum_weight;
206 sum_potential += real(w);
208 if (q == Quantity::Position) {
209 sum_position(0) += (u+sum_dr(0)+sum_wave_vector(0))*real(i*w);
210 sum_position(1) += (v+sum_dr(1)+sum_wave_vector(1))*real(i*w);
211 sum_position(2) +=
scale*real((k+i*sum_dr(2)+i*sum_wave_vector(2))*w);
213 sum_velocity(0) += omega*(u+sum_dr(0)+sum_wave_vector(0))*real(w);
214 sum_velocity(1) += omega*(v+sum_dr(1)+sum_wave_vector(1))*real(w);
215 sum_velocity(2) += -
scale*omega*k*real(i*w);
218 result(idx) = (q == Quantity::Position) ? sum_position : sum_velocity;
219 if (potential) { (*potential)(idx) = sum_potential; }
224 template <
class T>
void 227 const panel_array& panels,
228 const grid3& grid_txy,
229 vertex_field_3d& surface
231 const auto& _ = blitz::Range::all();
232 const auto& grid_xy = grid_txy.select(1, 2);
233 const T t = grid_txy.ubound(0);
235 {T{},grid_txy.lbound(1),grid_txy.lbound(2)},
236 {T{},grid_txy.ubound(1),grid_txy.ubound(2)},
237 {1,grid_txy.extent(1),grid_txy.extent(2)}};
238 Array<vertex_type,3> position(grid_zxy.shape());
239 generate_field(grid_zxy, position, t, panels, ship, Quantity::Position);
240 surface(grid_txy.end(0)-1,_,_) = position(0,_,_);
245 vtb::core::make_gerstner_solver<VTB_REAL_TYPE,3,vtb::core::Policy::OpenMP>() {
247 new Gerstner_solver_openmp<VTB_REAL_TYPE>
Trochoidal irrotational waves solves named after Gerstner.
const vec3 & position(int i=0) const
Get position or its time derivatives in Earth-fixed coordinate system.
static constexpr const T g()
Gravitational acceleration.
Rigid ship with a mass and translational and angular velocity.
static constexpr const T water_density()
Sea water density.
static constexpr T atmospheric_pressure()
Sea-level atmospheric pressure.
const vec3 & angular_velocity() const
Angular velocity in Earth-fixed coordinate system.
T scale(blitz::Array< T, N > x)
Return the difference between largest and smallest value in the array.
const vec3 & velocity() const
Get velocity in Earth-fixed coordinate system.
static constexpr const T pi()
Triangular ship hull panel (face).
void generate_field(const grid3 &grid_xyz, vertex_field_3d &result, T t, const panel_array &panels, const ship_type &ship, Quantity q, scalar_field_3d *potential=nullptr)