25#include <fhsim_environment/hydrodynamics/PanelClampLog.h>
26#include <fhsim_environment/hydrodynamics/PanelLoadLaw.h>
28#include <sfh/linalg/matrix_ops.h>
29#include <sfh/math/array.h>
30#include <sfh/math/math.h>
31#include <sfh/sim/kinematics.h>
32#include <sfh/util/diagnostic.h>
37namespace net_element_forces
41const double kMinMeshBarLength = 1.0e-10;
45const hydrodynamics::FlowReference kFlowReference = hydrodynamics::FlowReference::FreeStream;
105void CalcLocalUVComponents(
const PanelParams& params,
const T distAB_panel[3],
106 const T distAC_panel[3], T meshBarComp[6], T meshBarLength[2])
112 meshBarComp[2] = T(0.0);
115 meshBarComp[5] = T(0.0);
117 meshBarLength[0] = sfh::math::Max(
118 sqrt(meshBarComp[0] * meshBarComp[0] + meshBarComp[1] * meshBarComp[1]),
119 T(kMinMeshBarLength));
120 meshBarLength[1] = sfh::math::Max(
121 sqrt(meshBarComp[3] * meshBarComp[3] + meshBarComp[4] * meshBarComp[4]),
122 T(kMinMeshBarLength));
136PanelFrame<T> ComputePanelFrame(
const PanelParams& params,
const T*
const posA_ned,
137 const T*
const posB_ned,
const T*
const posC_ned)
143 sfh::sim::RMatrixFromThreePoints(posA_ned, posB_ned, posC_ned, frame.R_ned2panel);
147 T distAB_ned[3], distAC_ned[3];
148 T distAB_panel[3], distAC_panel[3];
149 sfh::math::ArraySubtract(posB_ned, posA_ned, distAB_ned, 3ul);
150 sfh::math::ArraySubtract(posC_ned, posA_ned, distAC_ned, 3ul);
151 sfh::sim::RotateToLocal(distAB_ned, frame.R_ned2panel, distAB_panel);
152 sfh::sim::RotateToLocal(distAC_ned, frame.R_ned2panel, distAC_panel);
154 CalcLocalUVComponents(params, distAB_panel, distAC_panel, frame.meshBarComp,
155 frame.meshBarLength);
160 T normBarCompU = T(0);
161 T normBarCompV = T(0);
162 for (
int i = 0; i < 3; i++) {
163 normBarCompU += frame.meshBarComp[i] * frame.meshBarComp[i];
164 normBarCompV += frame.meshBarComp[i + 3] * frame.meshBarComp[i + 3];
166 normBarCompU = sqrt(normBarCompU);
167 normBarCompV = sqrt(normBarCompV);
169 frame.meshOpeningAngle = 0.5 * acos(sfh::linalg::Dot(frame.meshBarComp, frame.meshBarComp + 3, 2ul) / (normBarCompU * normBarCompV));
170 if (!(frame.meshOpeningAngle == frame.meshOpeningAngle)) frame.meshOpeningAngle = T(0);
173 frame.area = 0.5 * sfh::math::Abs(distAB_panel[0] * distAC_panel[1] - distAB_panel[1] * distAC_panel[0]);
184void CalcTensionForces(
const PanelParams& params,
const T meshBarComp[6],
185 const T meshBarLength[2], T nodeATension_panel[3], T nodeBTension_panel[3],
186 T nodeCTension_panel[3])
193 twineTension[0] = (meshBarLength[0] > params.barL0)
194 ? params.eATwine * (meshBarLength[0] - params.barL0) / params.barL0
196 twineTension[1] = (meshBarLength[1] > params.barL0)
197 ? params.eATwine * (meshBarLength[1] - params.barL0) / params.barL0
199 twineTension[0] = sfh::math::Max(twineTension[0], T(0.0));
200 twineTension[1] = sfh::math::Max(twineTension[1], T(0.0));
202 nodeATension_panel[0] = params.nodesDistBC_mesh[1] * twineTension[0] * meshBarComp[0] / (2 * meshBarLength[0]) - params.nodesDistBC_mesh[0] * twineTension[1] * meshBarComp[3] / (2 * meshBarLength[1]);
203 nodeATension_panel[1] = params.nodesDistBC_mesh[1] * twineTension[0] * meshBarComp[1] / (2 * meshBarLength[0]) - params.nodesDistBC_mesh[0] * twineTension[1] * meshBarComp[4] / (2 * meshBarLength[1]);
204 nodeATension_panel[2] = T(0.0);
206 nodeBTension_panel[0] = -params.nodesDistAC_mesh[1] * twineTension[0] * meshBarComp[0] / (2 * meshBarLength[0]) + params.nodesDistAC_mesh[0] * twineTension[1] * meshBarComp[3] / (2 * meshBarLength[1]);
207 nodeBTension_panel[1] = -params.nodesDistAC_mesh[1] * twineTension[0] * meshBarComp[1] / (2 * meshBarLength[0]) + params.nodesDistAC_mesh[0] * twineTension[1] * meshBarComp[4] / (2 * meshBarLength[1]);
208 nodeBTension_panel[2] = T(0.0);
210 nodeCTension_panel[0] = params.nodesDistAB_mesh[1] * twineTension[0] * meshBarComp[0] / (2 * meshBarLength[0]) - params.nodesDistAB_mesh[0] * twineTension[1] * meshBarComp[3] / (2 * meshBarLength[1]);
211 nodeCTension_panel[1] = params.nodesDistAB_mesh[1] * twineTension[0] * meshBarComp[1] / (2 * meshBarLength[0]) - params.nodesDistAB_mesh[0] * twineTension[1] * meshBarComp[4] / (2 * meshBarLength[1]);
212 nodeCTension_panel[2] = T(0.0);
233hydrodynamics::PanelLoad<T> EvaluatePanelLoad(
const PanelParams& params,
const PanelFrame<T>& frame,
234 const hydrodynamics::PanelLoadLaw& law,
const hydrodynamics::Fluid& fluid,
const T& solidity,
235 const T elementVel_ned[3],
const T*
const waterVel_ned)
237 hydrodynamics::PanelGeometry<T> geometry;
238 geometry.area = frame.area;
240 hydrodynamics::Netting<T> netting;
241 netting.solidity = solidity;
242 netting.twineThickness = params.barD;
243 netting.hasBarDirections = params.meshDet != 0;
244 netting.barLength = params.barL0;
245 netting.knotDiameter = params.knotDiameter;
246 netting.numBarsU = params.numBarsU;
247 netting.numBarsV = params.numBarsV;
248 netting.numKnots = params.numKnots;
250 hydrodynamics::FlowSample<T> flow;
251 flow.reference = kFlowReference;
253 for (
int i = 0; i < 3; i++) {
254 geometry.normal[i] = frame.R_ned2panel[i][2];
255 flow.relativeVelocity[i] = waterVel_ned[i] - elementVel_ned[i];
258 const T barU = frame.R_ned2panel[i][0] * frame.meshBarComp[0] + frame.R_ned2panel[i][1] * frame.meshBarComp[1];
259 const T barV = frame.R_ned2panel[i][0] * frame.meshBarComp[3] + frame.R_ned2panel[i][1] * frame.meshBarComp[4];
260 netting.barU[i] = barU / frame.meshBarLength[0];
261 netting.barV[i] = barV / frame.meshBarLength[1];
264 return hydrodynamics::Evaluate(law, geometry, netting, fluid, flow);
270void CalcDampingForces(
const PanelParams& params,
const T elementVel_ned[3],
271 const T*
const velA_ned,
const T*
const velB_ned,
const T*
const velC_ned,
272 T dampingForcesNodeA_ned[3], T dampingForcesNodeB_ned[3],
273 T dampingForcesNodeC_ned[3],
double addedLinearDrag)
275 for (
unsigned short i = 0; i < 3; i++) {
276 dampingForcesNodeA_ned[i] = params.dampingCoeff * (elementVel_ned[i] - velA_ned[i]);
277 dampingForcesNodeB_ned[i] = params.dampingCoeff * (elementVel_ned[i] - velB_ned[i]);
278 dampingForcesNodeC_ned[i] = params.dampingCoeff * (elementVel_ned[i] - velC_ned[i]);
281 if (addedLinearDrag > 0) {
282 for (
unsigned short i = 0; i < 3; i++) {
283 dampingForcesNodeA_ned[i] -= addedLinearDrag / 3 * velA_ned[i];
284 dampingForcesNodeB_ned[i] -= addedLinearDrag / 3 * velB_ned[i];
285 dampingForcesNodeC_ned[i] -= addedLinearDrag / 3 * velC_ned[i];
314bool AddNodeForces(
const PanelParams& params,
const PanelFrame<T>& frame,
315 const hydrodynamics::PanelLoadLaw& law,
const hydrodynamics::Fluid& fluid,
const T& solidity,
316 const T*
const velA_ned,
const T*
const velB_ned,
const T*
const velC_ned,
317 const T*
const waterVel_ned, T*
const nodeAforce_ned, T*
const nodeBforce_ned,
318 T*
const nodeCforce_ned,
double addedLinearDrag = 0.0,
319 const hydrodynamics::PanelClampLog* clampLog =
nullptr)
321 T nodeATension_panel[3] = {T(0), T(0), T(0)};
322 T nodeBTension_panel[3] = {T(0), T(0), T(0)};
323 T nodeCTension_panel[3] = {T(0), T(0), T(0)};
324 if (params.twineStructure)
325 CalcTensionForces(params, frame.meshBarComp, frame.meshBarLength, nodeATension_panel,
326 nodeBTension_panel, nodeCTension_panel);
329 for (
int i = 0; i < 3; i++) {
330 elementVel_ned[i] = (velA_ned[i] + velB_ned[i] + velC_ned[i]) / 3.0;
333 const hydrodynamics::PanelLoad<T> load =
334 EvaluatePanelLoad(params, frame, law, fluid, solidity, elementVel_ned, waterVel_ned);
336 clampLog->Note(load.flags);
338 T dampingForcesNodeA_ned[3] = {T(0), T(0), T(0)};
339 T dampingForcesNodeB_ned[3] = {T(0), T(0), T(0)};
340 T dampingForcesNodeC_ned[3] = {T(0), T(0), T(0)};
341 if (params.twineStructure) {
342 CalcDampingForces(params, elementVel_ned, velA_ned, velB_ned, velC_ned,
343 dampingForcesNodeA_ned, dampingForcesNodeB_ned, dampingForcesNodeC_ned,
347 sfh::sim::RotateFromLocalAndAdd(nodeATension_panel, frame.R_ned2panel, nodeAforce_ned);
348 sfh::sim::RotateFromLocalAndAdd(nodeBTension_panel, frame.R_ned2panel, nodeBforce_ned);
349 sfh::sim::RotateFromLocalAndAdd(nodeCTension_panel, frame.R_ned2panel, nodeCforce_ned);
353 for (
int i = 0; i < 3; i++) {
354 const T hydroForcePerNode = load.force[i] / 3.0;
355 nodeAforce_ned[i] += hydroForcePerNode;
356 nodeBforce_ned[i] += hydroForcePerNode;
357 nodeCforce_ned[i] += hydroForcePerNode;
361 nodeAforce_ned[2] += params.NodeWeight;
362 nodeBforce_ned[2] += params.NodeWeight;
363 nodeCforce_ned[2] += params.NodeWeight;
365 if (params.twineStructure) {
366 for (
unsigned short i = 0; i < 3; i++) {
367 nodeAforce_ned[i] += dampingForcesNodeA_ned[i];
368 nodeBforce_ned[i] += dampingForcesNodeB_ned[i];
369 nodeCforce_ned[i] += dampingForcesNodeC_ned[i];
371 }
else if (addedLinearDrag > 0) {
373 for (
unsigned short i = 0; i < 3; i++) {
374 nodeAforce_ned[i] -= addedLinearDrag / 3 * velA_ned[i];
375 nodeBforce_ned[i] -= addedLinearDrag / 3 * velB_ned[i];
376 nodeCforce_ned[i] -= addedLinearDrag / 3 * velC_ned[i];
382 if constexpr (std::is_same_v<T, double>) {
383 const unsigned long none =
static_cast<unsigned long>(-1);
384 return sfh::util::FindBadValues(nodeAforce_ned, 3) == none && sfh::util::FindBadValues(nodeBforce_ned, 3) == none && sfh::util::FindBadValues(nodeCforce_ned, 3) == none;
Definition NetElement3NForces.h:85
T meshBarComp[6]
The u-bar in [0..2] and the v-bar in [3..5], panel frame.
Definition NetElement3NForces.h:87
T meshOpeningAngle
The mesh half opening angle, rad; 0 when undefined.
Definition NetElement3NForces.h:89
T R_ned2panel[3][3]
Columns: the panel x, y and z axes in the global frame.
Definition NetElement3NForces.h:86
T area
The element's area, m^2.
Definition NetElement3NForces.h:90
T meshBarLength[2]
The length of a u-bar and of a v-bar, bounded away from zero.
Definition NetElement3NForces.h:88
Definition NetElement3NForces.h:58
double meshDet
Mesh determinant, Priour (2005, Eq. 7); 0 for collinear corners.
Definition NetElement3NForces.h:62
double nodesDistBC_mesh[2]
Distance from node B to C in mesh (u,v) coordinates.
Definition NetElement3NForces.h:61
bool twineStructure
Definition NetElement3NForces.h:74
double knotDiameter
Diameter of the knots.
Definition NetElement3NForces.h:66
double eATwine
E-modulus times twine cross-sectional area.
Definition NetElement3NForces.h:64
double numKnots
Number of knots in the element, its number of meshes.
Definition NetElement3NForces.h:69
double nodesDistAB_mesh[2]
Distance from node A to B in mesh (u,v) coordinates.
Definition NetElement3NForces.h:59
double barD
Diameter of the twines.
Definition NetElement3NForces.h:65
double dampingCoeff
Definition NetElement3NForces.h:71
double NodeWeight
Weight in water carried by one node.
Definition NetElement3NForces.h:70
double barL0
Unstretched length of a mesh bar.
Definition NetElement3NForces.h:63
double numBarsV
Number of v-bars in the element, half its bar count.
Definition NetElement3NForces.h:68
double numBarsU
Number of u-bars in the element, half its bar count.
Definition NetElement3NForces.h:67
double nodesDistAC_mesh[2]
Distance from node A to C in mesh (u,v) coordinates.
Definition NetElement3NForces.h:60