9#include "cable/GaussPointDrag.h"
10#include "cable/WetCylinderWater.h"
12#include <fhsim_environment/hydrodynamics/CylinderHydro.h>
13#include <fhsim_environment/hydrodynamics/BodySubmergence.h>
14#include <fhsim_environment/hydrodynamics/WetCylinderLaw.h>
20#include <fhsim_coribo/eigen_matrix_defs.h>
21#include <fhsim_environment/EnvironmentProvider.h>
22#include <fhsim_environment/ElementFlowInteraction.h>
23#include <marenv/marenv.h>
25namespace trawl_cable_water
27using CoRiBoDynamics::mat3;
28using CoRiBoDynamics::vec3;
29using CoRiBoDynamics::vec6;
55inline double WetFraction(environment::EnvironmentProvider& environment,
double T,
const vec3& P,
const vec3& N,
const Segment& segment)
57 const vec3 endA = P - 0.5 * segment.
length * N;
58 const vec3 endB = P + 0.5 * segment.
length * N;
59 return environment::body_submergence::CylinderWetFraction(environment, environment.MaxWaveElevation(), T, endA.data(), endB.data(), segment.
radius);
64inline environment::wet_cylinder::WetCylinder CylinderOf(
const Segment& segment)
66 environment::wet_cylinder::WetCylinder cylinder {};
67 cylinder.length = segment.length;
68 cylinder.radius = segment.radius;
69 cylinder.volume = segment.displacementVolume;
70 cylinder.waterDensity = kRhoWater;
71 cylinder.inertia = environment::wet_cylinder::AddedMassInertia::CoriolisOnVelocity;
99inline vec6 InWaterForce(
const environment::wake::ElementFlowInteraction& flow,
double T,
const vec3& P,
const vec3& V,
const vec3& W,
const vec3& N,
const Segment& segment,
100 int point,
const wet_cylinder_water::EndWater* gaussWater =
nullptr)
102 using environment::wet_cylinder::Vector;
103 const auto water = gaussWater ? wet_cylinder_water::SampleWaterGivenVelocity(flow, T, P.data(), N.data(), segment.length, segment.radius, gaussWater->Mean())
104 : wet_cylinder_water::SampleWater(flow, T, P.data(), N.data(), segment.length, segment.radius, point);
106 vec6
Force = vec6::Zero();
107 const vec3 V_relative = V - vec3(water.waterVelocity.data());
108 const double v_abs2 = V_relative.squaredNorm();
109 Force(2) = kGravity * (segment.mass - kRhoWater * segment.displacementVolume * f);
114 const environment::wet_cylinder::WetCylinderState state {f, Vector {V(0), V(1), V(2)}, water.waterVelocity, Vector {W(0), W(1), W(2)}, Vector {N(0), N(1), N(2)}, water.waveAcceleration};
115 const auto cylinder = CylinderOf(segment);
116 const auto load = gaussWater ? environment::wet_cylinder::WaterLoadWithoutDrag(cylinder, environment::wet_cylinder::ReynoldsDrag {}, state)
117 : environment::wet_cylinder::WaterLoad(cylinder, environment::wet_cylinder::ReynoldsDrag {}, state);
118 Force.segment<3>(0) += vec3(load.coriolis.data());
120 const auto gauss = wet_cylinder_water::GaussPointDragLoad(cylinder, f, V, W, N, *gaussWater);
121 Force.segment<3>(0) += gauss.force;
122 Force.segment<3>(3) = gauss.moment;
123 }
else if (v_abs2 > 0)
124 Force.segment<3>(0) += vec3(load.drag.data());
125 Force.segment<3>(3) += vec3(load.torsion.data());
126 if (water.waveAcceleration)
127 Force.segment<3>(0) += vec3(load.morison.data());
157const double kDoorStallAngle = 0.66;
163inline double DoorDragCoefficient(
double alpha)
165 if (std::abs(alpha) > kDoorStallAngle) {
168 return 0.3 + std::abs(alpha) / kDoorStallAngle * 0.98;
175inline double DoorLiftCoefficient(
double alpha)
177 if (alpha > kDoorStallAngle) {
178 return std::tanh((0.0523 + kDoorStallAngle) * 3) * 2.5 * std::exp((kDoorStallAngle - alpha) * 3.0);
181 return std::tanh((0.0523 + alpha) * 3) * 2.5;
183 return std::tanh((0.0523 - 0.1) * 3) * 2.5 * std::exp((alpha + 0.1) * 3.0);
196inline vec6 DoorHydrodynamicForce(
const BodyState& state,
const Door& door,
const vec3& waterVelocity)
198 const vec3 Nx = state.rotation.col(0);
199 const vec3 Ny = state.rotation.col(1);
200 const vec3 Nz = state.rotation.col(2);
201 const vec3 W = state.angularVelocity;
203 const vec3 V = state.velocity - waterVelocity;
204 const double Vabs = V.norm();
205 const double VxAbs = V.dot(Nx);
206 const vec3 Vy = V.dot(Ny) * Ny;
207 const double VzAbs = V.dot(Nz);
209 const vec3 Vxz = V - Vy;
210 vec3 liftDirection = (Vxz.cross(Nz)).cross(Vxz);
211 liftDirection /= liftDirection.norm() + std::numeric_limits<double>::epsilon();
213 const double alpha = std::atan(-VzAbs / (VxAbs + std::numeric_limits<double>::epsilon()));
214 const double Cd = DoorDragCoefficient(alpha);
215 const double Cl = DoorLiftCoefficient(alpha);
217 vec6
Force = vec6::Zero();
218 const double Area = door.length * door.width;
219 const vec3 lift = 0.5 * kRhoWater * Area * Cl * Vabs * Vabs * liftDirection;
220 Force.segment<3>(0) += -0.5 * kRhoWater * Area * Vabs * (Cd * V) + lift;
221 const vec3 Wz = W.dot(Nz) * Nz;
222 const vec3 Wxy = W - Wz;
223 Force.segment<3>(3) += -0.5 * kRhoWater * Area * 0.7 * Area * W.norm() * (1.28 * Wxy + 0.1 * Wz);
235inline vec6 DoorForce(
const BodyState& state,
const Door& door,
const vec3& waterVelocity)
237 vec6
Force = DoorHydrodynamicForce(state, door, waterVelocity);
238 Force(2) += kGravity * (door.mass - door.displacementVolume * kRhoWater);
253inline vec6 ClumpWeightHydrodynamicForce(
const BodyState& state,
const ClumpWeight& clump,
const vec3& waterVelocity)
255 const vec3 Nz = state.rotation.col(2);
256 const vec3 W = state.angularVelocity;
258 const vec3 V = state.velocity - waterVelocity;
259 const double Vabs = V.norm();
260 const vec3 Vz = V.dot(Nz) * Nz;
261 const vec3 Vxy = V - Vz;
263 vec6
Force = vec6::Zero();
264 const double Area = clump.length * 2 * clump.radius;
265 Force.segment<3>(0) += -0.5 * kRhoWater * Area * Vabs * (1.1 * Vxy + 0.1 * Vz);
266 const vec3 Wz = W.dot(Nz) * Nz;
267 const vec3 Wxy = W - Wz;
268 Force.segment<3>(3) += -0.125 * kRhoWater * Area * 0.7 * Area * W.norm() * (1.28 * Wxy + 0.1 * Wz);
280inline vec6 ClumpWeightForce(
const BodyState& state,
const ClumpWeight& clump,
const vec3& waterVelocity)
282 vec6
Force = ClumpWeightHydrodynamicForce(state, clump, waterVelocity);
283 Force(2) += kGravity * (clump.mass - clump.length * clump.radius * clump.radius * std::numbers::pi * kRhoWater);
void Force(const double *pk, const double *pl, const double *vk, const double *current, double rho, double D, double force[3])
Definition CableSegmentDrag.h:40
constexpr double gravity
Gravity constant.
Definition marenv.h:19
constexpr double seawaterDensity
Ocean water density.
Definition marenv.h:20
The motion of a rigid body (a trawl door, a clump weight) for its water law.
Definition CableSegmentWaterForce.h:134
vec3 angularVelocity
Its angular velocity [rad/s].
Definition CableSegmentWaterForce.h:136
mat3 rotation
Its orientation: the columns are the body axes Nx, Ny, Nz.
Definition CableSegmentWaterForce.h:137
vec3 velocity
The velocity of its centre [m/s], NED.
Definition CableSegmentWaterForce.h:135
The properties of a clump weight, a cylinder along the body's z axis.
Definition CableSegmentWaterForce.h:151
double mass
The clump mass [kg].
Definition CableSegmentWaterForce.h:154
double length
The cylinder length [m].
Definition CableSegmentWaterForce.h:152
double radius
The cylinder radius [m].
Definition CableSegmentWaterForce.h:153
The properties of a trawl door, a flat plate in the body's x-z plane (normal Ny).
Definition CableSegmentWaterForce.h:142
double length
The plate length [m].
Definition CableSegmentWaterForce.h:143
double displacementVolume
The volume that gives the buoyancy [m³].
Definition CableSegmentWaterForce.h:146
double mass
The door mass [kg].
Definition CableSegmentWaterForce.h:145
double width
The plate width [m].
Definition CableSegmentWaterForce.h:144
The properties of the elements of one cable segment.
Definition CableSegmentWaterForce.h:33
double displacementVolume
The volume that gives the buoyancy [m³].
Definition CableSegmentWaterForce.h:37
double mass
The element mass [kg].
Definition CableSegmentWaterForce.h:36
double length
The element length [m].
Definition CableSegmentWaterForce.h:35
double radius
The drag radius [m].
Definition CableSegmentWaterForce.h:34
double wetFraction
f in [0, 1].
Definition WetCylinderWater.h:33