From 5c62ad725a873072f5008bf3851e4af2ff86d0a6 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Tue, 5 Apr 2022 16:47:15 -0600 Subject: [PATCH 1/4] move Reynolds number and friction coefficient to separate methods for readability --- .../aerodynamics/BarrowmanCalculator.java | 232 ++++++++++-------- 1 file changed, 130 insertions(+), 102 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 93e1a3632..9fcb5cea5 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -324,108 +324,14 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { */ private double calculateFrictionCD(FlightConfiguration configuration, FlightConditions conditions, Map map, WarningSet set) { - double c1 = 1.0, c2 = 1.0; double mach = conditions.getMach(); - double Re; - double Cf; + double Re = calculateReynoldsNumber(configuration, conditions); + double Cf = calculateFrictionCoefficient(configuration, mach, Re); + double roughnessCorrection = calculateRoughnessCorrection(mach); if (calcMap == null) buildCalcMap(configuration); - - Re = conditions.getVelocity() * configuration.getLength() / - conditions.getAtmosphericConditions().getKinematicViscosity(); - - // Calculate the skin friction coefficient (assume non-roughness limited) - if (configuration.getRocket().isPerfectFinish()) { - - // Assume partial laminar layer. Roughness-limitation is checked later. - if (Re < 1e4) { - // Too low, constant - Cf = 1.33e-2; - } else if (Re < 5.39e5) { - // Fully laminar - Cf = 1.328 / MathUtil.safeSqrt(Re); - } else { - // Transitional - Cf = 1.0 / pow2(1.50 * Math.log(Re) - 5.6) - 1700 / Re; - } - - // Compressibility correction - - if (mach < 1.1) { - // Below Re=1e6 no correction - if (Re > 1e6) { - if (Re < 3e6) { - c1 = 1 - 0.1 * pow2(mach) * (Re - 1e6) / 2e6; // transition to turbulent - } else { - c1 = 1 - 0.1 * pow2(mach); - } - } - } - if (mach > 0.9) { - if (Re > 1e6) { - if (Re < 3e6) { - c2 = 1 + (1.0 / Math.pow(1 + 0.045 * pow2(mach), 0.25) - 1) * (Re - 1e6) / 2e6; - } else { - c2 = 1.0 / Math.pow(1 + 0.045 * pow2(mach), 0.25); - } - } - } - - // Applying continuously around Mach 1 - if (mach < 0.9) { - Cf *= c1; - } else if (mach < 1.1) { - Cf *= (c2 * (mach - 0.9) / 0.2 + c1 * (1.1 - mach) / 0.2); - } else { - Cf *= c2; - } - - - } else { - - // Assume fully turbulent. Roughness-limitation is checked later. - if (Re < 1e4) { - // Too low, constant - Cf = 1.48e-2; - } else { - // Turbulent - Cf = 1.0 / pow2(1.50 * Math.log(Re) - 5.6); - } - - // Compressibility correction - - if (mach < 1.1) { - c1 = 1 - 0.1 * pow2(mach); - } - if (mach > 0.9) { - c2 = 1 / Math.pow(1 + 0.15 * pow2(mach), 0.58); - } - // Applying continuously around Mach 1 - if (mach < 0.9) { - Cf *= c1; - } else if (mach < 1.1) { - Cf *= c2 * (mach - 0.9) / 0.2 + c1 * (1.1 - mach) / 0.2; - } else { - Cf *= c2; - } - - } - - // Roughness-limited value correction term - double roughnessCorrection; - if (mach < 0.9) { - roughnessCorrection = 1 - 0.1 * pow2(mach); - } else if (mach > 1.1) { - roughnessCorrection = 1 / (1 + 0.18 * pow2(mach)); - } else { - c1 = 1 - 0.1 * pow2(0.9); - c2 = 1.0 / (1 + 0.18 * pow2(1.1)); - roughnessCorrection = c2 * (mach - 0.9) / 0.2 + c1 * (1.1 - mach) / 0.2; - } - - /* * Calculate the friction drag coefficient. @@ -445,11 +351,6 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { final InstanceMap imap = configuration.getActiveInstances(); for(Map.Entry> entry: imap.entrySet() ) { final RocketComponent c = entry.getKey(); - - // Consider only SymmetricComponents and FinSets: - if (!(c instanceof SymmetricComponent) && - !(c instanceof FinSet)) - continue; // iterate across component instances final ArrayList contextList = entry.getValue(); @@ -542,7 +443,134 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { return (finFriction + correction * bodyFriction) / conditions.getRefArea(); } + + + /** + * Calculation of Reynolds Number + * + * @param configuration Rocket configuration + * @param conditions Flight conditions taken into account + * @return Reynolds Number + */ + private double calculateReynoldsNumber(FlightConfiguration configuration, FlightConditions conditions) { + return conditions.getVelocity() * configuration.getLength() / + conditions.getAtmosphericConditions().getKinematicViscosity(); + } + /** + * Calculation of skin friction coefficient + * + * + * return skin friction coefficient + */ + private double calculateFrictionCoefficient(FlightConfiguration configuration, double mach, double Re) { + double Cf; + double c1 = 1.0, c2 = 1.0; + + // Calculate the skin friction coefficient (assume non-roughness limited) + if (configuration.getRocket().isPerfectFinish()) { + + // Assume partial laminar layer. Roughness-limitation is checked later. + if (Re < 1e4) { + // Too low, constant + Cf = 1.33e-2; + } else if (Re < 5.39e5) { + // Fully laminar + Cf = 1.328 / MathUtil.safeSqrt(Re); + } else { + // Transitional + Cf = 1.0 / pow2(1.50 * Math.log(Re) - 5.6) - 1700 / Re; + } + + // Compressibility correction + + if (mach < 1.1) { + // Below Re=1e6 no correction + if (Re > 1e6) { + if (Re < 3e6) { + c1 = 1 - 0.1 * pow2(mach) * (Re - 1e6) / 2e6; // transition to turbulent + } else { + c1 = 1 - 0.1 * pow2(mach); + } + } + } + if (mach > 0.9) { + if (Re > 1e6) { + if (Re < 3e6) { + c2 = 1 + (1.0 / Math.pow(1 + 0.045 * pow2(mach), 0.25) - 1) * (Re - 1e6) / 2e6; + } else { + c2 = 1.0 / Math.pow(1 + 0.045 * pow2(mach), 0.25); + } + } + } + + // Applying continuously around Mach 1 + if (mach < 0.9) { + Cf *= c1; + } else if (mach < 1.1) { + Cf *= (c2 * (mach - 0.9) / 0.2 + c1 * (1.1 - mach) / 0.2); + } else { + Cf *= c2; + } + + + } else { + + // Assume fully turbulent. Roughness-limitation is checked later. + if (Re < 1e4) { + // Too low, constant + Cf = 1.48e-2; + } else { + // Turbulent + Cf = 1.0 / pow2(1.50 * Math.log(Re) - 5.6); + } + + // Compressibility correction + + if (mach < 1.1) { + c1 = 1 - 0.1 * pow2(mach); + } + if (mach > 0.9) { + c2 = 1 / Math.pow(1 + 0.15 * pow2(mach), 0.58); + } + // Applying continuously around Mach 1 + if (mach < 0.9) { + Cf *= c1; + } else if (mach < 1.1) { + Cf *= c2 * (mach - 0.9) / 0.2 + c1 * (1.1 - mach) / 0.2; + } else { + Cf *= c2; + } + + } + + return Cf; + } + + /** + * Calculation of correction for roughness + * + * @param mach + * @return roughness correction + **/ + + private double calculateRoughnessCorrection(double mach) { + double c1, c2; + + // Roughness-limited value correction term + double roughnessCorrection; + if (mach < 0.9) { + roughnessCorrection = 1 - 0.1 * pow2(mach); + } else if (mach > 1.1) { + roughnessCorrection = 1 / (1 + 0.18 * pow2(mach)); + } else { + c1 = 1 - 0.1 * pow2(0.9); + c2 = 1.0 / (1 + 0.18 * pow2(1.1)); + roughnessCorrection = c2 * (mach - 0.9) / 0.2 + c1 * (1.1 - mach) / 0.2; + } + + return roughnessCorrection; + } /** * Calculation of drag coefficient due to pressure From 56949560c4c1dc1ea731510525f63be0d6843489 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Tue, 5 Apr 2022 17:00:19 -0600 Subject: [PATCH 2/4] Move component-level calculations out of instance loop --- .../aerodynamics/BarrowmanCalculator.java | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index 9fcb5cea5..d83d9ae83 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -351,45 +351,45 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { final InstanceMap imap = configuration.getActiveInstances(); for(Map.Entry> entry: imap.entrySet() ) { final RocketComponent c = entry.getKey(); + + //Handle Overriden CD for Whole Rocket + if(c.isCDOverridden()) { + continue; + } + // Calculate the roughness-limited friction coefficient + Finish finish = ((ExternalComponent) c).getFinish(); + if (Double.isNaN(roughnessLimited[finish.ordinal()])) { + roughnessLimited[finish.ordinal()] = + 0.032 * Math.pow(finish.getRoughnessSize() / configuration.getLength(), 0.2) * + roughnessCorrection; + } + + /* + * Actual Cf is maximum of Cf and the roughness-limited value. + * For perfect finish require additionally that Re > 1e6 + */ + double componentCf; + if (configuration.getRocket().isPerfectFinish()) { + + // For perfect finish require Re > 1e6 + if ((Re > 1.0e6) && (roughnessLimited[finish.ordinal()] > Cf)) { + componentCf = roughnessLimited[finish.ordinal()]; + } else { + componentCf = Cf; + } + + } else { + + // For fully turbulent use simple max + componentCf = Math.max(Cf, roughnessLimited[finish.ordinal()]); + + } + // iterate across component instances final ArrayList contextList = entry.getValue(); for(InstanceContext context: contextList ) { - // Calculate the roughness-limited friction coefficient - Finish finish = ((ExternalComponent) c).getFinish(); - if (Double.isNaN(roughnessLimited[finish.ordinal()])) { - roughnessLimited[finish.ordinal()] = - 0.032 * Math.pow(finish.getRoughnessSize() / configuration.getLength(), 0.2) * - roughnessCorrection; - } - - /* - * Actual Cf is maximum of Cf and the roughness-limited value. - * For perfect finish require additionally that Re > 1e6 - */ - double componentCf; - if (configuration.getRocket().isPerfectFinish()) { - - // For perfect finish require Re > 1e6 - if ((Re > 1.0e6) && (roughnessLimited[finish.ordinal()] > Cf)) { - componentCf = roughnessLimited[finish.ordinal()]; - } else { - componentCf = Cf; - } - - } else { - - // For fully turbulent use simple max - componentCf = Math.max(Cf, roughnessLimited[finish.ordinal()]); - - } - - //Handle Overriden CD for Whole Rocket - if(c.isCDOverridden()) { - continue; - } - // Calculate the friction drag: if (c instanceof SymmetricComponent) { From 632b48f8df7079e1095e4c36f596f67b3d06333e Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Tue, 5 Apr 2022 19:30:10 -0600 Subject: [PATCH 3/4] Create RocketComponentCalc::calculateFrictionCD() Move actual friction CD calculation code into subclasses of RocketComponentCalc() LaunchLugCalc adds so little wetted area it isn't worth bothering with, so isn't calculated (wasn't calculated before, either) TubeFinSetCalc also doesn't calculate it; that's coming next. --- .../aerodynamics/BarrowmanCalculator.java | 45 +++++++------------ .../aerodynamics/barrowman/FinSetCalc.java | 6 +++ .../aerodynamics/barrowman/LaunchLugCalc.java | 6 +++ .../barrowman/RocketComponentCalc.java | 12 ++++- .../barrowman/SymmetricComponentCalc.java | 9 +++- .../barrowman/TubeFinSetCalc.java | 6 +++ 6 files changed, 53 insertions(+), 31 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index d83d9ae83..bc1b09d29 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -323,7 +323,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { * @return friction drag for entire rocket */ private double calculateFrictionCD(FlightConfiguration configuration, FlightConditions conditions, - Map map, WarningSet set) { + Map map, WarningSet warningSet) { double mach = conditions.getMach(); double Re = calculateReynoldsNumber(configuration, conditions); @@ -341,8 +341,8 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { * for thickness as we go on. */ - double finFriction = 0; - double bodyFriction = 0; + double finFrictionCD = 0; + double bodyFrictionCD = 0; double maxR = 0, minX = Double.MAX_VALUE, maxX = 0; double[] roughnessLimited = new double[Finish.values().length]; @@ -351,8 +351,11 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { final InstanceMap imap = configuration.getActiveInstances(); for(Map.Entry> entry: imap.entrySet() ) { final RocketComponent c = entry.getKey(); - - //Handle Overriden CD for Whole Rocket + + if (!c.isAerodynamic()) + continue; + + // Handle Overriden CD for Whole Rocket if(c.isCDOverridden()) { continue; } @@ -389,20 +392,11 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { // iterate across component instances final ArrayList contextList = entry.getValue(); for(InstanceContext context: contextList ) { - - - // Calculate the friction drag: + double componentFrictionCD = calcMap.get(c).calculateFrictionCD(conditions, componentCf, warningSet); + if (c instanceof SymmetricComponent) { - SymmetricComponent s = (SymmetricComponent) c; - - bodyFriction += componentCf * s.getComponentWetArea(); - - if (map != null) { - // Corrected later - map.get(c).setFrictionCD(componentCf * s.getComponentWetArea() - / conditions.getRefArea()); - } + bodyFrictionCD += componentFrictionCD; final double componentMinX = context.getLocation().x; minX = Math.min(minX, componentMinX); @@ -414,16 +408,11 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { maxR = Math.max(maxR, componentMaxR); } else if (c instanceof FinSet) { - - FinSet f = (FinSet) c; - double mac = ((FinSetCalc) calcMap.get(c)).getMACLength(); - double cd = componentCf * (1 + 2 * f.getThickness() / mac) * - 2 * f.getPlanformArea(); - finFriction += cd; - - if (map != null) { - map.get(c).setFrictionCD(cd / conditions.getRefArea()); - } + finFrictionCD += componentFrictionCD; + } + + if (map != null) { + map.get(c).setFrictionCD(componentFrictionCD); } } } @@ -441,7 +430,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { } } - return (finFriction + correction * bodyFriction) / conditions.getRefArea(); + return finFrictionCD + correction * bodyFrictionCD; } diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java index 7aaf412b3..10b0569f8 100644 --- a/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java +++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java @@ -621,6 +621,12 @@ public class FinSetCalc extends RocketComponentCalc { // } // // } + + @Override + public double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warnings) { + double cd = componentCf * (1 + 2 * thickness / macLength) * 2; + return cd; + } @Override public double calculatePressureCD(FlightConditions conditions, diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/LaunchLugCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/LaunchLugCalc.java index 7563574b6..179a4d9a0 100644 --- a/core/src/net/sf/openrocket/aerodynamics/barrowman/LaunchLugCalc.java +++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/LaunchLugCalc.java @@ -30,6 +30,12 @@ public class LaunchLugCalc extends RocketComponentCalc { // Nothing to be done } + @Override + public double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warnings) { + // launch lug doesn't add enough area to worry about + return 0; + } + @Override public double calculatePressureCD(FlightConditions conditions, double stagnationCD, double baseCD, WarningSet warnings) { diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/RocketComponentCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/RocketComponentCalc.java index e24ab8785..63d90cafd 100644 --- a/core/src/net/sf/openrocket/aerodynamics/barrowman/RocketComponentCalc.java +++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/RocketComponentCalc.java @@ -28,6 +28,16 @@ public abstract class RocketComponentCalc { public abstract void calculateNonaxialForces(FlightConditions conditions, Transformation transform, AerodynamicForces forces, WarningSet warnings); + + /** + * Calculates the friction drag of the component. + * + * @param conditions the flight conditions + * @param componentCF component coefficient of friction, calculated in BarrowmanCalculator + * @param warnings set in which to to store possible warnings + * @return the friction drag coefficient of the component + */ + public abstract double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warnings); /** * Calculates the pressure drag of the component. This component does NOT include @@ -37,7 +47,7 @@ public abstract class RocketComponentCalc { * @param stagnationCD the current stagnation drag coefficient * @param baseCD the current base drag coefficient * @param warnings set in which to store possible warnings - * @return the pressure drag of the component + * @return the pressure drag coefficient of the component */ public abstract double calculatePressureCD(FlightConditions conditions, double stagnationCD, double baseCD, WarningSet warnings); diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/SymmetricComponentCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/SymmetricComponentCalc.java index 679215b90..6a7e8cafc 100644 --- a/core/src/net/sf/openrocket/aerodynamics/barrowman/SymmetricComponentCalc.java +++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/SymmetricComponentCalc.java @@ -45,6 +45,7 @@ public class SymmetricComponentCalc extends RocketComponentCalc { private final double frontalArea; private final double fullVolume; private final double planformArea, planformCenter; + private final double wetArea; private final double sinphi; public SymmetricComponentCalc(RocketComponent c) { @@ -53,7 +54,6 @@ public class SymmetricComponentCalc extends RocketComponentCalc { throw new IllegalArgumentException("Illegal component type " + c); } SymmetricComponent component = (SymmetricComponent) c; - length = component.getLength(); foreRadius = component.getForeRadius(); @@ -63,6 +63,8 @@ public class SymmetricComponentCalc extends RocketComponentCalc { fullVolume = component.getFullVolume(); planformArea = component.getComponentPlanformArea(); planformCenter = component.getComponentPlanformCenter(); + + wetArea = component.getComponentWetArea(); if (component instanceof BodyTube) { shape = null; @@ -174,7 +176,10 @@ public class SymmetricComponentCalc extends RocketComponentCalc { conditions.getSinAOA() * conditions.getSincAOA()); // sin(aoa)^2 / aoa } - + @Override + public double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warningSet) { + return componentCf * wetArea / conditions.getRefArea(); + } private LinearInterpolator interpolator = null; diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java index f9a1ecf4f..261cff8e0 100644 --- a/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java +++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/TubeFinSetCalc.java @@ -672,5 +672,11 @@ public class TubeFinSetCalc extends RocketComponentCalc { return 3 * component.getFinCount(); } + + @Override + public double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warnings) { + // launch lug doesn't add enough area to worry about + return 0; + } } From 3ef3bdcbab2e540a1c244e084863cdd1acbe5888 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Fri, 15 Apr 2022 17:04:36 -0600 Subject: [PATCH 4/4] Fix typo in FinSetCalc --- .../net/sf/openrocket/aerodynamics/BarrowmanCalculator.java | 5 +++-- .../net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java index bc1b09d29..d24c9c69c 100644 --- a/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java +++ b/core/src/net/sf/openrocket/aerodynamics/BarrowmanCalculator.java @@ -585,6 +585,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { final InstanceMap imap = configuration.getActiveInstances(); for(Map.Entry> entry: imap.entrySet() ) { final RocketComponent c = entry.getKey(); + if (!c.isAerodynamic()) continue; @@ -596,7 +597,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { double cd = calcMap.get(c).calculatePressureCD(conditions, stagnation, base, warningSet); total += cd; - + if (forceMap != null) { forceMap.get(c).setPressureCD(cd); } @@ -625,7 +626,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator { } } } - + return total; } diff --git a/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java b/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java index a713d9d53..438cbbc46 100644 --- a/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java +++ b/core/src/net/sf/openrocket/aerodynamics/barrowman/FinSetCalc.java @@ -624,7 +624,7 @@ public class FinSetCalc extends RocketComponentCalc { @Override public double calculateFrictionCD(FlightConditions conditions, double componentCf, WarningSet warnings) { - double cd = componentCf * (1 + 2 * thickness / macLength) * 2; + double cd = componentCf * (1 + 2 * thickness / macLength) * 2 * finArea / conditions.getRefArea(); return cd; }