28#include "PanelFormulas.h"
29#include "PanelLoadTypes.h"
30#include "TwineFriction.h"
34namespace hydrodynamics
40const double kMinReynolds = 31.622776601683793;
42const double kMaxReynolds = 1.0e4;
45const double kMaxSolidity = 0.5;
52const double kMinSolidity = 1.0e-4;
55const double kMinSpeed = 1.0e-10;
58const unsigned kFlagSolidityClamped = 1u;
60const unsigned kFlagReynoldsClamped = 2u;
62const unsigned kFlagSpeedBelowEpsilon = 4u;
64const unsigned kFlagVelocityRatioClamped = kPanelFlagVelocityRatioClamped;
71const double kB2 = 1.0;
79const double kMaxA3 = 0.25;
87const double kMinA3 = -0.125;
95const double kMaxAbsB4 = 0.5;
98using panel_formulas::CylinderDragCoefficient;
108T ScreenDragCoefficient(
const T& cylinderCd,
const T& solidity)
110 const T open = 1.0 - solidity;
111 return cylinderCd * solidity * (2.0 - solidity) / (2.0 * open * open);
125T SchubauerLiftCoefficient(
const T& cd)
129 const double quarterPi = 0.78539816339744830962;
130 const T normal = 0.5 * cd;
131 const T tangential = quarterPi * 4.0 * normal / (8.0 + normal);
132 return (normal - tangential) / sqrt(2.0);
136using panel_formulas::VelocityReductionFactor;
145T InductionFactor(
const T& solidity)
147 return 0.5 * (1.0 + VelocityReductionFactor(solidity));
158T LocalDragCoefficient(
const T& panelCd,
const T& solidity)
160 const T open = 1.0 - solidity;
161 const T onePlusR = 1.0 + VelocityReductionFactor(solidity);
162 return panelCd * 4.0 * open * open / (solidity * onePlusR * onePlusR);
172T ClampAndFlag(
const T& value,
double lower,
double upper,
unsigned flag,
unsigned& flags)
174 if (!(value >= lower)) {
217Inflow<T> ComputeInflow(
const T velocity[3],
const T normal[3],
unsigned& flags)
225 sqrt(velocity[0] * velocity[0] + velocity[1] * velocity[1] + velocity[2] * velocity[2]);
227 T guardedSpeed = inflow.
speed;
228 if (inflow.
speed < kMinSpeed) {
229 flags |= kFlagSpeedBelowEpsilon;
230 guardedSpeed = T(kMinSpeed);
233 T normalComponent = T(0.0);
234 for (
int i = 0; i < 3; i++) {
235 inflow.
direction[i] = velocity[i] / guardedSpeed;
236 normalComponent = normalComponent + inflow.
direction[i] * normal[i];
239 inflow.
cosTheta = abs(normalComponent);
245 for (
int i = 0; i < 3; i++) {
247 normalComponent * normal[i] - normalComponent * normalComponent * inflow.
direction[i];
260T DragAngleFactor(
const T& cosTheta,
double a3)
262 const T cos3Theta = (4.0 * cosTheta * cosTheta - 3.0) * cosTheta;
263 return (1.0 - a3) * cosTheta + a3 * cos3Theta;
275T LiftAngleFactorPerSinCos(
const T& cosTheta,
double b4)
277 const T cos2Theta = 2.0 * cosTheta * cosTheta - 1.0;
278 return 2.0 * kB2 + 4.0 * b4 * cos2Theta;
307PanelLoad<T> EvaluateScreen(
double a3,
double b4,
bool withInduction,
308 const PanelGeometry<T>& panel,
const Netting<T>& netting,
const Fluid& fluid,
309 const FlowSample<T>& flow)
313 PanelLoad<T> load {};
317 ClampAndFlag(netting.solidity, kMinSolidity, kMaxSolidity, kFlagSolidityClamped, load.flags);
318 const Inflow<T> inflow = ComputeInflow(flow.relativeVelocity, panel.normal, load.flags);
320 const T velocityRatio = VelocityReductionFactor(solidity, load.flags);
321 const T induction = withInduction ? 0.5 * (1.0 + velocityRatio) : T(1.0);
324 load.throughFlowSpeed = induction * inflow.speed / (1.0 - solidity);
325 load.reynolds = load.throughFlowSpeed * netting.twineThickness / fluid.nu;
328 ClampAndFlag(load.reynolds, kMinReynolds, kMaxReynolds, kFlagReynoldsClamped, load.flags);
331 const T cdWithoutInduction = ScreenDragCoefficient(CylinderDragCoefficient(reynolds), solidity);
332 const T inductionSquared = induction * induction;
333 const T cd = cdWithoutInduction * inductionSquared;
334 const T cl = inductionSquared * SchubauerLiftCoefficient(cdWithoutInduction);
336 const T dragCoefficient = cd * DragAngleFactor(inflow.cosTheta, a3);
337 const T liftPerSinCos = cl * LiftAngleFactorPerSinCos(inflow.cosTheta, b4);
338 const T sinTheta = sqrt(1.0 - inflow.cosTheta * inflow.cosTheta);
339 const T liftCoefficient = liftPerSinCos * sinTheta * inflow.cosTheta;
340 const T dynamicForce = 0.5 * fluid.rho * panel.area * inflow.speed * inflow.speed;
342 const twine_friction::InPlaneFriction<T> friction = twine_friction::EvaluateTwineFriction(
343 netting, fluid, solidity, flow.relativeVelocity, panel.normal);
344 const T guardedSpeed = inflow.speed < kMinSpeed ? T(kMinSpeed) : inflow.speed;
345 const T frictionDragPerQ = friction.drag / (0.5 * fluid.rho * guardedSpeed * guardedSpeed);
346 const T totalDragPerQ = panel.area * dragCoefficient + frictionDragPerQ;
348 for (
int i = 0; i < 3; i++) {
349 load.force[i] = dynamicForce * (dragCoefficient * inflow.direction[i] + liftPerSinCos * inflow.liftBasis[i])
352 load.drag = dynamicForce * dragCoefficient + friction.drag;
353 load.lift = dynamicForce * liftCoefficient + friction.lift;
354 load.theta = inflow.theta;
355 load.momentumDeficit = totalDragPerQ;
356 load.localCd = LocalDragCoefficient(dragCoefficient + frictionDragPerQ / panel.area, solidity);
The inflow on a panel: its speed, direction and angle to the normal.
Definition KF2012Common.h:189
T theta
rad, in [0, pi/2].
Definition KF2012Common.h:193
T liftBasis[3]
Definition KF2012Common.h:204
T direction[3]
U-hat = U / max(|U|, kMinSpeed).
Definition KF2012Common.h:191
T speed
|U|, m/s.
Definition KF2012Common.h:190
T cosTheta
cos(theta) = |U-hat . n|, in [0, 1].
Definition KF2012Common.h:192