FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
NetElement3NForces.h
1#pragma once
2
35#include <sfh/linalg/matrix_ops.h>
36#include <sfh/math/array.h>
37#include <sfh/math/math.h>
38#include <sfh/sim/kinematics.h>
39#include <sfh/util/diagnostic.h>
40
41#include <cmath>
42#include <iostream>
43#include <type_traits>
44
45namespace net_element_forces
46{
47
49const double kMinMeshBarLength = 1.0e-10;
51const double kMinHydDynVel = 1.0e-10;
52const double kMaxHydDynVel = 1.0e10;
54const double kMaxNormalDrag = 1.0e100;
55const double kMaxTangentialDrag = 1.0e100;
57const double kSaturationVel = 500.0;
58
59
70{
71 double nodesDistAB_mesh[2];
72 double nodesDistAC_mesh[2];
73 double nodesDistBC_mesh[2];
74 double meshDet;
75 double barL0;
76 double eATwine;
77 double barD;
78 double ny_water;
79 double TurbLimit;
80 double LamLimit;
82 double CnLinear;
83 double CnTurb;
84 double CnLam;
85 double kTwineDragNormal[2];
86 double Ct;
87 double kKnot;
88 double NodeWeight;
89 double dampingCoeff;
90};
91
92
103template<class T>
104void CalcLocalUVComponents(const PanelParams& params, const T distAB_panel[3],
105 const T distAC_panel[3], T meshBarComp[6], T meshBarLength[2])
106{
107 using std::sqrt;
108
109 meshBarComp[0] = (params.nodesDistAC_mesh[1] * distAB_panel[0] - params.nodesDistAB_mesh[1] * distAC_panel[0]) / params.meshDet;
110 meshBarComp[1] = (params.nodesDistAC_mesh[1] * distAB_panel[1] - params.nodesDistAB_mesh[1] * distAC_panel[1]) / params.meshDet;
111 meshBarComp[2] = T(0.0);
112 meshBarComp[3] = (params.nodesDistAB_mesh[0] * distAC_panel[0] - params.nodesDistAC_mesh[0] * distAB_panel[0]) / params.meshDet;
113 meshBarComp[4] = (params.nodesDistAB_mesh[0] * distAC_panel[1] - params.nodesDistAC_mesh[0] * distAB_panel[1]) / params.meshDet;
114 meshBarComp[5] = T(0.0);
115
116 meshBarLength[0] = sfh::math::Max(
117 sqrt(meshBarComp[0] * meshBarComp[0] + meshBarComp[1] * meshBarComp[1]),
118 T(kMinMeshBarLength));
119 meshBarLength[1] = sfh::math::Max(
120 sqrt(meshBarComp[3] * meshBarComp[3] + meshBarComp[4] * meshBarComp[4]),
121 T(kMinMeshBarLength));
122}
123
124
130template<class T>
131void CalcTensionForces(const PanelParams& params, const T meshBarComp[6],
132 const T meshBarLength[2], T nodeATension_panel[3], T nodeBTension_panel[3],
133 T nodeCTension_panel[3])
134{
135 // The original multiplied by the `bool` of this comparison. That promotes to 1.0 or 0.0
136 // for a built-in type but discards the derivative of a differentiable one, so the branch
137 // is written out. The retained branch is the original expression unchanged, and
138 // multiplying it by an exact 1.0 was exact, so the `double` value is unaffected.
139 T twineTension[2];
140 twineTension[0] = (meshBarLength[0] > params.barL0)
141 ? params.eATwine * (meshBarLength[0] - params.barL0) / params.barL0
142 : T(0.0);
143 twineTension[1] = (meshBarLength[1] > params.barL0)
144 ? params.eATwine * (meshBarLength[1] - params.barL0) / params.barL0
145 : T(0.0);
146 twineTension[0] = sfh::math::Max(twineTension[0], T(0.0));
147 twineTension[1] = sfh::math::Max(twineTension[1], T(0.0));
148
149 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]);
150 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]);
151 nodeATension_panel[2] = T(0.0);
152
153 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]);
154 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]);
155 nodeBTension_panel[2] = T(0.0);
156
157 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]);
158 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]);
159 nodeCTension_panel[2] = T(0.0);
160}
161
162
181template<class T>
182T CalcVelocities(const PanelParams& params, const T& meshOpeningAngle,
183 const T R_ned2panel[3][3], const T* const velA_ned, const T* const velB_ned,
184 const T* const velC_ned, const T* const waterVel_ned, T elementVel_ned[3],
185 T hydDynVel_ned[3], T hydDynVel_panel[3])
186{
187 using std::cos;
188 using std::sin;
189 using std::sqrt;
190
191 for (int i = 0; i < 3; i++) {
192 elementVel_ned[i] = (velA_ned[i] + velB_ned[i] + velC_ned[i]) / 3.0;
193 }
194
195 const T speed = sfh::math::Norm(elementVel_ned, 3);
196 if (speed > kSaturationVel) {
197 sfh::math::Normalize3(elementVel_ned);
198 for (unsigned short i = 0; i < 3; i++) {
199 elementVel_ned[i] = elementVel_ned[i] * kSaturationVel;
200 }
201 }
202
203 // Default value for the effect of knots on solidity; should be specified when applicable.
204 const double knotFactor = 1.1;
205
206 T Sn = knotFactor * (params.barD) / (params.barL0 * sin(meshOpeningAngle) * cos(meshOpeningAngle));
207
208 // Keeps Sn finite and within the bounds given by Kristiansen and Faltinsen (2012). The
209 // comparisons are on the value, so they select a branch and say nothing about any
210 // derivative the scalar type carries; in the clamped branches the solidity is a constant
211 // and its derivative is correctly zero.
212 if (!(Sn == Sn) || Sn + 1.0 == Sn) Sn = T(0.1); // Check for NaN or infinity.
213 if (Sn > 0.5) Sn = T(0.5);
214 if (Sn <= 0) Sn = T(0.0001);
215
216 const T snFactor = sqrt(2 - Sn) / (sqrt(2.0) * (1 - Sn));
217
218 T waterVelModified_ned[3];
219 waterVelModified_ned[0] = waterVel_ned[0] * snFactor;
220 waterVelModified_ned[1] = waterVel_ned[1] * snFactor;
221 waterVelModified_ned[2] = waterVel_ned[2] * snFactor;
222
223 sfh::math::ArraySubtract(elementVel_ned, waterVelModified_ned, hydDynVel_ned, 3ul);
224 sfh::sim::RotateToLocal(hydDynVel_ned, R_ned2panel, hydDynVel_panel);
225
226 return sfh::math::Bound(sfh::math::Norm(hydDynVel_panel, 3), T(kMinHydDynVel),
227 T(kMaxHydDynVel));
228}
229
230
238template<class T>
239void CalcHydroDynamicForces(const PanelParams& params, const T& meshOpeningAngle,
240 const T meshBarComp[6], const T meshBarLength[2], const T R_ned2panel[3][3],
241 const T* const velA_ned, const T* const velB_ned, const T* const velC_ned,
242 const T* const waterVel_ned, T elementVel_ned[3], T totalDragPerNode_panel[3])
243{
244 using std::asin;
245 using std::log10;
246
247 T hydDynVel_ned[3];
248 T hydDynVel_panel[3];
249 const T hydDynVel_absolute = CalcVelocities(params, meshOpeningAngle, R_ned2panel,
250 velA_ned, velB_ned, velC_ned, waterVel_ned, elementVel_ned, hydDynVel_ned,
251 hydDynVel_panel);
252
253 // The local z-component of the mesh bars is zero, the element being plane, so the local
254 // z-component of the velocity does not contribute to these products.
255 T hydDynVel_dot_meshBarComp[2];
256 hydDynVel_dot_meshBarComp[0] = sfh::linalg::Dot(hydDynVel_panel, meshBarComp, 2ul);
257 hydDynVel_dot_meshBarComp[1] = sfh::linalg::Dot(hydDynVel_panel, meshBarComp + 3, 2ul);
258
259 const T k0 = hydDynVel_dot_meshBarComp[0] / (meshBarLength[0] * meshBarLength[0]);
260 const T k1 = hydDynVel_dot_meshBarComp[1] / (meshBarLength[1] * meshBarLength[1]);
261
262 T hydDynVel_tangential_panel[6];
263 for (int i = 0; i < 3; i++) {
264 hydDynVel_tangential_panel[i] = k0 * meshBarComp[i];
265 hydDynVel_tangential_panel[i + 3] = k1 * meshBarComp[i + 3];
266 }
267
268 T hydDynVel_tangential_absolute[2];
269 hydDynVel_tangential_absolute[0] = sfh::math::Max(T(kMinHydDynVel),
270 sfh::math::Norm(hydDynVel_tangential_panel, 3));
271 hydDynVel_tangential_absolute[1] = sfh::math::Max(T(kMinHydDynVel),
272 sfh::math::Norm(hydDynVel_tangential_panel + 3, 3));
273
274 T hydDynVel_normal_panel[6];
275 sfh::math::ArraySubtract(hydDynVel_panel, hydDynVel_tangential_panel,
276 hydDynVel_normal_panel, 3ul);
277 sfh::math::ArraySubtract(hydDynVel_panel, hydDynVel_tangential_panel + 3,
278 hydDynVel_normal_panel + 3, 3ul);
279
280 T hydDynVel_normal_absolute[2];
281 hydDynVel_normal_absolute[0] = sfh::math::Max(T(kMinHydDynVel),
282 sfh::math::Norm(hydDynVel_normal_panel, 3));
283 hydDynVel_normal_absolute[1] = sfh::math::Max(T(kMinHydDynVel),
284 sfh::math::Norm(hydDynVel_normal_panel + 3, 3));
285
286 // The angle of attack between the effective hydrodynamic velocity and each bar family.
287 T sin_hydDynAngle[2];
288 sin_hydDynAngle[0] = hydDynVel_normal_absolute[0] / hydDynVel_absolute;
289 sin_hydDynAngle[1] = hydDynVel_normal_absolute[1] / hydDynVel_absolute;
290
291 for (int i = 0; i < 2; i++) {
292 if (sin_hydDynAngle[i] > 1) {
293 sin_hydDynAngle[i] = T(1);
294 } else if (sin_hydDynAngle[i] < -1) {
295 sin_hydDynAngle[i] = T(-1);
296 }
297 }
298
299 T hydDynAngle[2];
300 hydDynAngle[0] = asin(sin_hydDynAngle[0]);
301 hydDynAngle[1] = asin(sin_hydDynAngle[1]);
302
303 // Reynolds number from the absolute velocity and the twine diameter, not accounting for
304 // the angle between the twines and the effective hydrodynamic velocity.
305 const T nominalReynoldsNumber = hydDynVel_absolute * params.barD / params.ny_water;
306
307 T Cn[2];
308 if ((nominalReynoldsNumber >= 32) && (nominalReynoldsNumber < 10000)) {
309 // Seventh order polynomial fit of the drag coefficient of a smooth cylinder against
310 // the Reynolds number (Kristiansen and Faltinsen, 2012).
311 const T log10Re = log10(nominalReynoldsNumber);
312 const T pow2Re = log10Re * log10Re;
313 const T pow3Re = pow2Re * log10Re;
314 const T pow4Re = pow2Re * pow2Re;
315 const T pow5Re = pow2Re * pow3Re;
316 const T pow6Re = pow3Re * pow3Re;
317 const T pow7Re = pow3Re * pow4Re;
318
319 const double A = -78.46675;
320 const double B1 = 254.73873;
321 const double B2 = -327.8864;
322 const double B3 = 223.64577;
323 const double B4 = -87.92234;
324 const double B5 = 20.00769;
325 const double B6 = -2.44894;
326 const double B7 = 0.12479;
327
328 Cn[0] = A + B1 * log10Re + B2 * pow2Re + B3 * pow3Re + B4 * pow4Re + B5 * pow5Re + B6 * pow6Re + B7 * pow7Re;
329 Cn[0] = Cn[0] * sin_hydDynAngle[0];
330 Cn[1] = A + B1 * log10Re + B2 * pow2Re + B3 * pow3Re + B4 * pow4Re + B5 * pow5Re + B6 * pow6Re + B7 * pow7Re;
331 Cn[1] = Cn[1] * sin_hydDynAngle[1];
332 } else {
333 // A linear model below four degrees and the modified cross-flow principle above it,
334 // for the Reynolds numbers where the polynomial fit is invalid. Both limits account
335 // for the twines' angle to the flow lengthening the hydrodynamic length.
336 const T angleTurb = asin(nominalReynoldsNumber / params.TurbLimit);
337 const T angleLam = asin(nominalReynoldsNumber / params.LamLimit);
338
339 for (int i = 0; i < 2; i++) {
340 if (hydDynAngle[i] < params.CnLinearLimitAngle) {
341 Cn[i] = T(params.CnLinear);
342 } else if (hydDynAngle[i] < angleTurb) {
343 Cn[i] = params.CnTurb * sin_hydDynAngle[i];
344 } else if (hydDynAngle[i] <= angleLam) {
345 Cn[i] = (params.CnTurb + (hydDynAngle[i] - angleTurb) / (angleLam - angleTurb) * (params.CnLam - params.CnTurb)) * sin_hydDynAngle[i];
346 } else {
347 Cn[i] = params.CnLam * sin_hydDynAngle[i];
348 }
349 }
350 }
351
352 T twineDragNormal[2];
353 T twineDragTangential[2];
354 twineDragNormal[0] = params.kTwineDragNormal[0] * hydDynVel_absolute * Cn[0];
355 twineDragNormal[1] = params.kTwineDragNormal[1] * hydDynVel_absolute * Cn[1];
356 twineDragTangential[0] = params.kTwineDragNormal[0] * hydDynVel_absolute * params.Ct;
357 twineDragTangential[1] = params.kTwineDragNormal[1] * hydDynVel_absolute * params.Ct;
358
359 twineDragNormal[0] =
360 sfh::math::Bound(twineDragNormal[0], T(-kMaxNormalDrag), T(kMaxNormalDrag));
361 twineDragNormal[1] =
362 sfh::math::Bound(twineDragNormal[1], T(-kMaxNormalDrag), T(kMaxNormalDrag));
363 twineDragTangential[0] = sfh::math::Bound(twineDragTangential[0],
364 T(-kMaxTangentialDrag), T(kMaxTangentialDrag));
365 twineDragTangential[1] = sfh::math::Bound(twineDragTangential[1],
366 T(-kMaxTangentialDrag), T(kMaxTangentialDrag));
367
368 // Drag on the knots acts along the effective hydrodynamic velocity, with no tangential
369 // component.
370 const T knotDrag = params.kKnot * hydDynVel_absolute * hydDynVel_absolute;
371
372 T twineDragNormal_panel[6];
373 T twineDragTangential_panel[6];
374 for (int i = 0; i < 3; i++) {
375 twineDragNormal_panel[i] = -twineDragNormal[0] * hydDynVel_normal_panel[i];
376 twineDragNormal_panel[i + 3] = -twineDragNormal[1] * hydDynVel_normal_panel[i + 3];
377 twineDragTangential_panel[i] =
378 -twineDragTangential[0] * hydDynVel_tangential_panel[i];
379 twineDragTangential_panel[i + 3] =
380 -twineDragTangential[1] * hydDynVel_tangential_panel[i + 3];
381 }
382
383 T knotDrag_panel[3];
384 knotDrag_panel[0] = -knotDrag * hydDynVel_panel[0] / hydDynVel_absolute;
385 knotDrag_panel[1] = -knotDrag * hydDynVel_panel[1] / hydDynVel_absolute;
386 knotDrag_panel[2] = -knotDrag * hydDynVel_panel[2] / hydDynVel_absolute;
387
388 for (unsigned short i = 0; i < 3; i++) {
389 totalDragPerNode_panel[i] = (twineDragNormal_panel[i] + twineDragNormal_panel[i + 3] + twineDragTangential_panel[i] + twineDragTangential_panel[i + 3] + knotDrag_panel[i]) / 3;
390 }
391
392 // Retained because the original computed them and a reader will look for them; the
393 // tangential magnitudes are not used in the force itself.
394 (void)hydDynVel_tangential_absolute;
395}
396
397
399template<class T>
400void CalcDampingForces(const PanelParams& params, const T elementVel_ned[3],
401 const T* const velA_ned, const T* const velB_ned, const T* const velC_ned,
402 T dampingForcesNodeA_ned[3], T dampingForcesNodeB_ned[3],
403 T dampingForcesNodeC_ned[3], double addedLinearDrag)
404{
405 for (unsigned short i = 0; i < 3; i++) {
406 dampingForcesNodeA_ned[i] = params.dampingCoeff * (elementVel_ned[i] - velA_ned[i]);
407 dampingForcesNodeB_ned[i] = params.dampingCoeff * (elementVel_ned[i] - velB_ned[i]);
408 dampingForcesNodeC_ned[i] = params.dampingCoeff * (elementVel_ned[i] - velC_ned[i]);
409 }
410
411 if (addedLinearDrag > 0) {
412 for (unsigned short i = 0; i < 3; i++) {
413 dampingForcesNodeA_ned[i] -= addedLinearDrag / 3 * velA_ned[i];
414 dampingForcesNodeB_ned[i] -= addedLinearDrag / 3 * velB_ned[i];
415 dampingForcesNodeC_ned[i] -= addedLinearDrag / 3 * velC_ned[i];
416 }
417 }
418}
419
420
440template<class T>
441void AddNodeForces(const PanelParams& params, const T* const posA_ned,
442 const T* const posB_ned, const T* const posC_ned, const T* const velA_ned,
443 const T* const velB_ned, const T* const velC_ned, const T* const waterVel_ned,
444 T* const nodeAforce_ned, T* const nodeBforce_ned, T* const nodeCforce_ned,
445 double hydroForcesRatio = 1.0, double addedLinearDrag = 0.0)
446{
447 using std::acos;
448 using std::sqrt;
449
450 // The panel x-axis lies along the AB side, the y-axis spans towards C, and the z-axis
451 // completes a right-handed system.
452 T R_ned2panel[3][3];
453 sfh::sim::RMatrixFromThreePoints(posA_ned, posB_ned, posC_ned, R_ned2panel);
454
455 // The panel-frame separations. They are held as 3-vectors although the third component
456 // is always zero, so that the standard rotation and array routines apply.
457 T distAB_ned[3], distAC_ned[3];
458 T distAB_panel[3], distAC_panel[3];
459 sfh::math::ArraySubtract(posB_ned, posA_ned, distAB_ned, 3ul);
460 sfh::math::ArraySubtract(posC_ned, posA_ned, distAC_ned, 3ul);
461 sfh::sim::RotateToLocal(distAB_ned, R_ned2panel, distAB_panel);
462 sfh::sim::RotateToLocal(distAC_ned, R_ned2panel, distAC_panel);
463
464 T meshBarComp_panel[6];
465 T meshBarLength[2];
466 CalcLocalUVComponents(params, distAB_panel, distAC_panel, meshBarComp_panel,
467 meshBarLength);
468
469 // The mesh half opening angle, from the scalar product of the u- and v-bar vectors
470 // (Priour, 2001, p. 232). The positive mesh directions must be defined so that the half
471 // angle is the one between bars that would naturally tend to close.
472 T normBarCompU = T(0);
473 T normBarCompV = T(0);
474 for (int i = 0; i < 3; i++) {
475 normBarCompU += meshBarComp_panel[i] * meshBarComp_panel[i];
476 normBarCompV += meshBarComp_panel[i + 3] * meshBarComp_panel[i + 3];
477 }
478 normBarCompU = sqrt(normBarCompU);
479 normBarCompV = sqrt(normBarCompV);
480
481 T meshOpeningAngle = 0.5 * acos(sfh::linalg::Dot(meshBarComp_panel, meshBarComp_panel + 3, 2ul) / (normBarCompU * normBarCompV));
482 if (!(meshOpeningAngle == meshOpeningAngle)) meshOpeningAngle = T(0);
483
484 T nodeATension_panel[3] = {T(0), T(0), T(0)};
485 T nodeBTension_panel[3] = {T(0), T(0), T(0)};
486 T nodeCTension_panel[3] = {T(0), T(0), T(0)};
487 CalcTensionForces(params, meshBarComp_panel, meshBarLength, nodeATension_panel,
488 nodeBTension_panel, nodeCTension_panel);
489
490 T elementVel_ned[3];
491 T totalDragPerNode_panel[3];
492 CalcHydroDynamicForces(params, meshOpeningAngle, meshBarComp_panel, meshBarLength,
493 R_ned2panel, velA_ned, velB_ned, velC_ned, waterVel_ned, elementVel_ned,
494 totalDragPerNode_panel);
495
496 T dampingForcesNodeA_ned[3] = {T(0), T(0), T(0)};
497 T dampingForcesNodeB_ned[3] = {T(0), T(0), T(0)};
498 T dampingForcesNodeC_ned[3] = {T(0), T(0), T(0)};
499 CalcDampingForces(params, elementVel_ned, velA_ned, velB_ned, velC_ned,
500 dampingForcesNodeA_ned, dampingForcesNodeB_ned, dampingForcesNodeC_ned,
501 addedLinearDrag);
502
503 // The hydrodynamic force is shared equally between the three nodes. Local z-components
504 // of the tension are zero, the element being plane.
505 T nodeAforce_panel[3];
506 T nodeBforce_panel[3];
507 T nodeCforce_panel[3];
508 for (int i = 0; i < 3; i++) {
509 nodeAforce_panel[i] = nodeATension_panel[i];
510 nodeBforce_panel[i] = nodeBTension_panel[i];
511 nodeCforce_panel[i] = nodeCTension_panel[i];
512
513 nodeAforce_panel[i] += hydroForcesRatio * totalDragPerNode_panel[i];
514 nodeBforce_panel[i] += hydroForcesRatio * totalDragPerNode_panel[i];
515 nodeCforce_panel[i] += hydroForcesRatio * totalDragPerNode_panel[i];
516 }
517
518 sfh::sim::RotateFromLocalAndAdd(nodeAforce_panel, R_ned2panel, nodeAforce_ned);
519 sfh::sim::RotateFromLocalAndAdd(nodeBforce_panel, R_ned2panel, nodeBforce_ned);
520 sfh::sim::RotateFromLocalAndAdd(nodeCforce_panel, R_ned2panel, nodeCforce_ned);
521
522 // The weight in water of the netting, distributed equally between the three nodes.
523 nodeAforce_ned[2] += params.NodeWeight;
524 nodeBforce_ned[2] += params.NodeWeight;
525 nodeCforce_ned[2] += params.NodeWeight;
526
527 for (unsigned short i = 0; i < 3; i++) {
528 nodeAforce_ned[i] += dampingForcesNodeA_ned[i];
529 nodeBforce_ned[i] += dampingForcesNodeB_ned[i];
530 nodeCforce_ned[i] += dampingForcesNodeC_ned[i];
531 }
532
533 // The diagnostic below reads raw `double` arrays, so it applies only to the `double`
534 // instantiation. It is unchanged in that case.
535 if constexpr (std::is_same_v<T, double>) {
536 unsigned long bad;
537 if ((bad = sfh::util::FindBadValues(nodeAforce_ned, 3)) != (unsigned long)-1)
538 std::cout << "Bad element in nodeAforce_ned: " << bad << std::endl;
539 if ((bad = sfh::util::FindBadValues(nodeBforce_ned, 3)) != (unsigned long)-1)
540 std::cout << "Bad element in nodeBforce_ned: " << bad << std::endl;
541 if ((bad = sfh::util::FindBadValues(nodeCforce_ned, 3)) != (unsigned long)-1)
542 std::cout << "Bad element in nodeCforce_ned: " << bad << std::endl;
543 }
544}
545
546} // namespace net_element_forces
Definition NetElement3NForces.h:70
double CnLinearLimitAngle
Angle below which the linear Cn model applies.
Definition NetElement3NForces.h:81
double meshDet
Mesh determinant, Priour (2005, Eq. 7).
Definition NetElement3NForces.h:74
double Ct
Tangential drag coefficient, times pi.
Definition NetElement3NForces.h:86
double nodesDistBC_mesh[2]
Distance from node B to C in mesh (u,v) coordinates.
Definition NetElement3NForces.h:73
double CnTurb
Constant of the turbulent cross-flow Cn model.
Definition NetElement3NForces.h:83
double eATwine
E-modulus times twine cross-sectional area.
Definition NetElement3NForces.h:76
double kKnot
Precomputed knot drag factor.
Definition NetElement3NForces.h:87
double CnLam
Constant of the laminar cross-flow Cn model.
Definition NetElement3NForces.h:84
double ny_water
Kinematic viscosity of water.
Definition NetElement3NForces.h:78
double nodesDistAB_mesh[2]
Distance from node A to B in mesh (u,v) coordinates.
Definition NetElement3NForces.h:71
double TurbLimit
Upper limit of the turbulent boundary layer.
Definition NetElement3NForces.h:79
double barD
Diameter of the twines.
Definition NetElement3NForces.h:77
double kTwineDragNormal[2]
Precomputed normal twine drag factor, per bar family.
Definition NetElement3NForces.h:85
double dampingCoeff
Coefficient of the rotational and structural damping.
Definition NetElement3NForces.h:89
double NodeWeight
Weight in water carried by one node.
Definition NetElement3NForces.h:88
double barL0
Unstretched length of a mesh bar.
Definition NetElement3NForces.h:75
double CnLinear
Constant of the linear Cn model.
Definition NetElement3NForces.h:82
double nodesDistAC_mesh[2]
Distance from node A to C in mesh (u,v) coordinates.
Definition NetElement3NForces.h:72
double LamLimit
Lower limit of the laminar boundary layer.
Definition NetElement3NForces.h:80