FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
CableSegmentWaterForce.h
1#pragma once
2
9#include "cable/GaussPointDrag.h"
10#include "cable/WetCylinderWater.h"
11
12#include <fhsim_environment/hydrodynamics/CylinderHydro.h>
13#include <fhsim_environment/hydrodynamics/BodySubmergence.h>
14#include <fhsim_environment/hydrodynamics/WetCylinderLaw.h>
15
16#include <algorithm>
17#include <cmath>
18#include <numbers>
19#include <limits>
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>
24
25namespace trawl_cable_water
26{
27using CoRiBoDynamics::mat3;
28using CoRiBoDynamics::vec3;
29using CoRiBoDynamics::vec6;
30
32struct Segment
33{
34 double radius;
35 double length;
36 double mass;
38};
39
40const double kRhoWater = marenv::seawaterDensity;
41const double kGravity = marenv::gravity;
42
43
55inline double WetFraction(environment::EnvironmentProvider& environment, double T, const vec3& P, const vec3& N, const Segment& segment)
56{
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);
60}
61
64inline environment::wet_cylinder::WetCylinder CylinderOf(const Segment& segment)
65{
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;
72 return cylinder;
73}
74
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)
101{
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);
105 const double f = water.wetFraction;
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);
110 if (f > 0.0) {
111 // The wet-cylinder law: the Coriolis force of the added mass on the velocity relative to the water (MARE-0323), the
112 // independence principle (Cd on the cross-flow Reynolds number, Ct on the total-speed one, ENV-0104, ENV-0105), the
113 // skin-friction moment on the spin (MARE-0376) and the Morison inertia force (R104, MARE-0314).
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());
119 if (gaussWater) {
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());
128 }
129 return Force;
130}
131
134{
135 vec3 velocity;
137 mat3 rotation;
138};
139
141struct Door
142{
143 double length;
144 double width;
145 double mass;
147};
148
151{
152 double length;
153 double radius;
154 double mass;
155};
156
157const double kDoorStallAngle = 0.66;
158
163inline double DoorDragCoefficient(double alpha)
164{
165 if (std::abs(alpha) > kDoorStallAngle) {
166 return 1.28;
167 }
168 return 0.3 + std::abs(alpha) / kDoorStallAngle * 0.98;
169}
170
175inline double DoorLiftCoefficient(double alpha)
176{
177 if (alpha > kDoorStallAngle) {
178 return std::tanh((0.0523 + kDoorStallAngle) * 3) * 2.5 * std::exp((kDoorStallAngle - alpha) * 3.0);
179 }
180 if (alpha > -0.1) {
181 return std::tanh((0.0523 + alpha) * 3) * 2.5;
182 }
183 return std::tanh((0.0523 - 0.1) * 3) * 2.5 * std::exp((alpha + 0.1) * 3.0);
184}
185
196inline vec6 DoorHydrodynamicForce(const BodyState& state, const Door& door, const vec3& waterVelocity)
197{
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;
202
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);
208
209 const vec3 Vxz = V - Vy;
210 vec3 liftDirection = (Vxz.cross(Nz)).cross(Vxz);
211 liftDirection /= liftDirection.norm() + std::numeric_limits<double>::epsilon();
212
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);
216
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);
224 return Force;
225}
226
235inline vec6 DoorForce(const BodyState& state, const Door& door, const vec3& waterVelocity)
236{
237 vec6 Force = DoorHydrodynamicForce(state, door, waterVelocity);
238 Force(2) += kGravity * (door.mass - door.displacementVolume * kRhoWater);
239 return Force;
240}
241
253inline vec6 ClumpWeightHydrodynamicForce(const BodyState& state, const ClumpWeight& clump, const vec3& waterVelocity)
254{
255 const vec3 Nz = state.rotation.col(2);
256 const vec3 W = state.angularVelocity;
257
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;
262
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);
269 return Force;
270}
271
280inline vec6 ClumpWeightForce(const BodyState& state, const ClumpWeight& clump, const vec3& waterVelocity)
281{
282 vec6 Force = ClumpWeightHydrodynamicForce(state, clump, waterVelocity);
283 Force(2) += kGravity * (clump.mass - clump.length * clump.radius * clump.radius * std::numbers::pi * kRhoWater);
284 return Force;
285}
286
287} // namespace trawl_cable_water
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