/** Evaluate effective AoA (i.e., taking into account airfoil twist) */
  public double calculateAlphaEffective() {
    _alphaEffective =
        Amount.valueOf(
            geometry.get_twist().getEstimatedValue() + _alphaRoot.getEstimatedValue(), SI.RADIAN);

    return _alphaEffective.getEstimatedValue();
  }
  /**
   * This function plots the airfoil drag polar using a parabolic approssimation.
   *
   * @author Manuela Ruocco
   */
  public void plotPolar() {
    System.out.println("\n \n-----------------------------------------------------");
    System.out.println("STARTING PLOT AIRFOIL DRAG POLAR");
    System.out.println("-----------------------------------------------------");

    MyArray alphaArray = new MyArray();
    int _numberOfAlpha = 40;
    double[] cdArrayPolar = new double[_numberOfAlpha];
    double[] clArrayPolar = new double[_numberOfAlpha];
    Amount<Angle> alphaActualAmount;

    Amount<Angle> alphaStart = Amount.valueOf(toRadians(-6.), SI.RADIAN);
    Amount<Angle> alphaEnd = Amount.valueOf(toRadians(12.), SI.RADIAN);

    alphaArray.setDouble(
        MyArrayUtils.linspace(
            alphaStart.getEstimatedValue(), alphaEnd.getEstimatedValue(), _numberOfAlpha));

    String folderPathPolar =
        MyConfiguration.currentDirectoryString + File.separator + "out" + File.separator;
    String subfolderPathPolar =
        JPADStaticWriteUtils.createNewFolder(folderPathPolar + "Polar_Airfoil" + File.separator);

    for (int i = 0; i < _numberOfAlpha; i++) {
      alphaActualAmount = Amount.valueOf(alphaArray.get(i), SI.RADIAN);
      clArrayPolar[i] = calculateClAtAlpha(alphaActualAmount.getEstimatedValue());
      cdArrayPolar[i] = calculateCdAtAlpha(alphaActualAmount);
    }

    MyChartToFileUtils.plotNoLegend(
        cdArrayPolar,
        clArrayPolar,
        null,
        null,
        null,
        null,
        "Cd",
        "Cl",
        "",
        "",
        subfolderPathPolar,
        "Polar_Airfoil ");

    System.out.println("\n \n-----------------------------------------------------");
    System.out.println("DONE");
    System.out.println("-----------------------------------------------------");
  }
Example #3
0
 public Finocyl() {
   try {
     setLength(Amount.valueOf(70, SI.MILLIMETER));
   } catch (PropertyVetoException e) {
     e.printStackTrace();
   }
   generateGeometry();
 }
  public void plotClvsAlpha(String subfolderPath, String name) {

    System.out.println("\n \n-----------------------------------------------------");
    System.out.println("STARTING PLOT AIRFOIL CL vs ALPHA CURVE " + name);
    System.out.println("-----------------------------------------------------");

    MyArray alphaArray = new MyArray();
    int _numberOfAlpha = 60;
    double[] clArray = new double[_numberOfAlpha];
    double[] alphaArrayDeg = new double[_numberOfAlpha];

    Amount<Angle> alphaActualAmount;
    Amount<Angle> alphaStart = Amount.valueOf(toRadians(-6.), SI.RADIAN);
    Amount<Angle> alphaEnd = Amount.valueOf(toRadians(25.0), SI.RADIAN);

    alphaArray.setDouble(
        MyArrayUtils.linspace(
            alphaStart.getEstimatedValue(), alphaEnd.getEstimatedValue(), _numberOfAlpha));

    for (int i = 0; i < _numberOfAlpha; i++) {
      alphaActualAmount = Amount.valueOf(alphaArray.get(i), SI.RADIAN);
      clArray[i] = calculateClAtAlpha(alphaActualAmount.getEstimatedValue());
      alphaArrayDeg[i] = alphaActualAmount.to(NonSI.DEGREE_ANGLE).getEstimatedValue();
    }

    MyChartToFileUtils.plotNoLegend(
        alphaArrayDeg,
        clArray,
        null,
        null,
        null,
        null,
        "alpha",
        "CL",
        "deg",
        "",
        subfolderPath,
        "CL vs alpha Airfoil" + name);

    System.out.println("-----------------------------------------------------");
    System.out.println("\n DONE");
    System.out.println("-----------------------------------------------------");
  }
  public double calculateCdAtClLinear(double cl) {
    double qValue = _clStar - _clAlpha.getEstimatedValue() * _alphaStar.getEstimatedValue();
    Amount<Angle> alpha;
    double alphaTemp;
    alphaTemp = (cl - qValue) / _clAlpha.getEstimatedValue();

    alpha = Amount.valueOf(alphaTemp, SI.RADIAN);

    double cdAirfoil = calculateCdAtAlpha(alpha);
    return cdAirfoil;
  }
  public InputOutputTree() {

    alphaCurrent = Amount.valueOf(0.0, NonSI.DEGREE_ANGLE);
    alphaInitial = Amount.valueOf(0.0, NonSI.DEGREE_ANGLE);
    alphaFinal = Amount.valueOf(0.0, NonSI.DEGREE_ANGLE);
    sweepLE = Amount.valueOf(0.0, NonSI.DEGREE_ANGLE);

    altitude = Amount.valueOf(0.0, SI.METER);

    surface = Amount.valueOf(0.0, SI.SQUARE_METRE);

    chordDistribution = new ArrayList<Amount>();
    xLEDistribution = new ArrayList<Amount>();
    dihedralDistribution = new ArrayList<Amount>();
    twistDistribution = new ArrayList<Amount>();

    alphaZeroLiftDistribution = new ArrayList<Amount>();
    alphaStarDistribution = new ArrayList<Amount>();
    maximumliftCoefficientDistribution = new ArrayList<Double>();
    yAdimensionalStationInput = new ArrayList<Double>();

    machNumber = 0.0;
    aspectRatio = 0.0;
    adimensionalKinkStation = 0.0;
    meanThickness = 0.0;

    numberOfAlpha = 0;
    numberOfPointSemispan = 0;
    numberOfSections = 0;

    cLVsAlphaVector = new double[numberOfAlphaCL];
    alphaVector = new double[numberOfAlphaCL];
  }
Example #7
0
public class ConstraintUtils {

  private static final Amount<Duration> ZERO = Amount.valueOf(0, SI.SECOND);

  public static PeriodicTemporalConstraint createConstraint(
      EPlanElement element,
      Timepoint endpoint,
      Amount<Duration> earliest,
      Amount<Duration> latest,
      String rationale) {
    PeriodicTemporalConstraint constraint =
        ConstraintsFactory.eINSTANCE.createPeriodicTemporalConstraint();
    constraint.getPoint().setElement(element);
    constraint.getPoint().setEndpoint(endpoint);
    constraint.setEarliest(earliest);
    constraint.setLatest(latest);
    constraint.setRationale(rationale);
    return constraint;
  }

  public static BinaryTemporalConstraint createConstraint(
      EPlanElement elementA,
      Timepoint endpointA,
      EPlanElement elementB,
      Timepoint endpointB,
      Amount<Duration> min,
      Amount<Duration> max,
      String rationale) {
    BinaryTemporalConstraint constraint =
        ConstraintsFactory.eINSTANCE.createBinaryTemporalConstraint();
    constraint.getPointA().setElement(elementA);
    constraint.getPointA().setEndpoint(endpointA);
    constraint.getPointB().setElement(elementB);
    constraint.getPointB().setEndpoint(endpointB);
    constraint.setMinimumBminusA(min);
    constraint.setMaximumBminusA(max);
    constraint.setRationale(rationale);
    return constraint;
  }

  public static ConstraintPoint createConstraintPoint(
      EPlanElement planElement, Timepoint timepoint) {
    ConstraintPoint constraintPoint = ConstraintsFactory.eINSTANCE.createConstraintPoint();
    constraintPoint.setElement(planElement);
    constraintPoint.setEndpoint(timepoint);
    return constraintPoint;
  }

  /*
   * Periodic constraint utilities
   */

  public static Date getPeriodicConstraintEarliestDate(PeriodicTemporalConstraint constraint) {
    Amount<Duration> earliest = constraint.getEarliest();
    if (earliest != null) {
      Date midnight = getPeriodicConstraintDate(constraint);
      if (midnight != null) {
        return DateUtils.add(midnight, earliest);
      }
    }
    return null;
  }

  public static Date getPeriodicConstraintLatestDate(PeriodicTemporalConstraint constraint) {
    Amount<Duration> latest = constraint.getLatest();
    if (latest != null) {
      Date midnight = getPeriodicConstraintDate(constraint);
      if (midnight != null) {
        return DateUtils.add(midnight, latest);
      }
    }
    return null;
  }

  private static Date getPeriodicConstraintDate(PeriodicTemporalConstraint constraint) {
    ConstraintPoint point = constraint.getPoint();
    Date date = point.getDate();
    if (date == null) {
      return null;
    }
    return MissionCalendarUtils.getMidnight(date);
  }

  public static Amount<Duration> getPeriodicConstraintOffset(Date date) {
    if (date == null) {
      return null;
    }
    Date midnight = MissionCalendarUtils.getMidnight(date);
    Amount<Duration> offset = DateUtils.subtract(date, midnight);
    return offset;
  }

  /*
   * Attach/detach constraints
   */

  public static void attachConstraint(final PeriodicTemporalConstraint constraint) {
    ConstraintsMember member =
        constraint.getPoint().getElement().getMember(ConstraintsMember.class, true);
    member.getPeriodicTemporalConstraints().add(constraint);
  }

  public static void detachConstraint(final PeriodicTemporalConstraint constraint) {
    ConstraintsMember member =
        constraint.getPoint().getElement().getMember(ConstraintsMember.class, true);
    member.getPeriodicTemporalConstraints().remove(constraint);
  }

  public static void attachConstraint(final BinaryTemporalConstraint constraint) {
    ConstraintsMember memberA =
        constraint.getPointA().getElement().getMember(ConstraintsMember.class, true);
    memberA.getBinaryTemporalConstraints().add(constraint);
    ConstraintsMember memberB =
        constraint.getPointB().getElement().getMember(ConstraintsMember.class, true);
    memberB.getBinaryTemporalConstraints().add(constraint);
  }

  public static void detachConstraint(final BinaryTemporalConstraint constraint) {
    EPlanElement elementA = constraint.getPointA().getElement();
    if (elementA != null) {
      ConstraintsMember memberA = elementA.getMember(ConstraintsMember.class, true);
      memberA.getBinaryTemporalConstraints().remove(constraint);
    }
    EPlanElement elementB = constraint.getPointB().getElement();
    if (elementB != null) {
      ConstraintsMember memberB = elementB.getMember(ConstraintsMember.class, true);
      memberB.getBinaryTemporalConstraints().remove(constraint);
    }
  }

  /*
   * Access constraints
   */

  public static Collection<ConstraintsMember> getConstraintMembersRecursively(EPlan plan) {
    return EPlanUtils.getMembers(plan, ConstraintsMember.class);
  }

  public static List<PeriodicTemporalConstraint> getPeriodicConstraints(
      EPlanElement element, boolean mustExist) {
    ConstraintsMember constraintsMember = element.getMember(ConstraintsMember.class, mustExist);
    if (constraintsMember == null) {
      return Collections.emptyList();
    }
    return constraintsMember.getPeriodicTemporalConstraints();
  }

  /**
   * Gets the constraint with the Earliest and Latest Start or End of a plan element.
   *
   * @param element -- activity or group
   * @param whichEnd -- START or END
   * @return null if unconstrained, else the constraint
   */
  public static PeriodicTemporalConstraint getPeriodicConstraint(
      EPlanElement element, Timepoint whichEnd) {
    List<PeriodicTemporalConstraint> periodicConstraints = getPeriodicConstraints(element, false);
    if (periodicConstraints == null) return null;
    for (PeriodicTemporalConstraint constraint : periodicConstraints) {
      if (whichEnd == constraint.getPoint().getEndpoint()) {
        return constraint;
      }
    }
    return null;
  }

  public static List<PeriodicTemporalConstraint> getPeriodicConstraints(
      EPlanElement element, Timepoint timepoint, boolean mustExist) {
    ConstraintsMember constraintsMember = element.getMember(ConstraintsMember.class, mustExist);
    if (constraintsMember == null) {
      return Collections.emptyList();
    }
    List<PeriodicTemporalConstraint> result = new ArrayList<PeriodicTemporalConstraint>();
    for (PeriodicTemporalConstraint constraint :
        constraintsMember.getPeriodicTemporalConstraints()) {
      ConstraintPoint point = constraint.getPoint();
      if ((point.getElement() == element) && (point.getEndpoint() == timepoint)) {
        result.add(constraint);
      }
    }
    return result;
  }

  public static List<BinaryTemporalConstraint> getBinaryConstraints(
      EPlanElement element, boolean mustExist) {
    ConstraintsMember constraintsMember = element.getMember(ConstraintsMember.class, mustExist);
    if (constraintsMember == null) {
      return Collections.emptyList();
    }
    return constraintsMember.getBinaryTemporalConstraints();
  }

  public static List<BinaryTemporalConstraint> getBinaryConstraints(
      EPlanElement element, Timepoint timepoint, boolean mustExist) {
    ConstraintsMember constraintsMember = element.getMember(ConstraintsMember.class, mustExist);
    if (constraintsMember == null) {
      return Collections.emptyList();
    }
    List<BinaryTemporalConstraint> result = new ArrayList<BinaryTemporalConstraint>();
    for (BinaryTemporalConstraint constraint : constraintsMember.getBinaryTemporalConstraints()) {
      ConstraintPoint pointA = constraint.getPointA();
      ConstraintPoint pointB = constraint.getPointB();
      if (((pointA.getElement() == element) && (pointA.getEndpoint() == timepoint))
          || ((pointB.getElement() == element) && (pointB.getEndpoint() == timepoint))) {
        result.add(constraint);
      }
    }
    return result;
  }

  public static List<BinaryTemporalConstraint> getBinaryStartConstraints(
      EPlanElement element, boolean mustExist) {
    return getBinaryConstraints(element, Timepoint.START, mustExist);
  }

  public static List<BinaryTemporalConstraint> getBinaryEndConstraints(
      EPlanElement element, boolean mustExist) {
    return getBinaryConstraints(element, Timepoint.END, mustExist);
  }

  /**
   * Given a particular constraint and EPlan (the context of the plan elements), this method will
   * determine the elements that the constraint constrains.
   *
   * @param constraint
   * @param ePlan
   * @return
   */
  public static LinkedHashSet<EPlanElement> getConstrainedEPlanElements(
      BinaryTemporalConstraint constraint) {
    LinkedHashSet<EPlanElement> elements = new LinkedHashSet<EPlanElement>();
    elements.add(constraint.getPointA().getElement());
    elements.add(constraint.getPointB().getElement());
    return elements;
  }

  /**
   * Creates a new binary constraint which is the reverse but equivalent to the original constraint.
   * For example, "A must end before B starts" can also be stated as "B must start after A ends".
   *
   * @param originalConstraint
   * @return
   */
  public static BinaryTemporalConstraint reverseConstraint(
      BinaryTemporalConstraint originalConstraint) {
    if (originalConstraint == null) {
      // Might happen if an activity was removed or filtered out of an import.
      return null;
    }

    BinaryTemporalConstraint newConstraint = EMFUtils.copy(originalConstraint);

    newConstraint.getPointA().setElement(originalConstraint.getPointB().getElement());
    newConstraint.getPointA().setEndpoint(originalConstraint.getPointB().getEndpoint());
    newConstraint.getPointA().setAnchor(originalConstraint.getPointB().getAnchor());
    newConstraint.getPointB().setElement(originalConstraint.getPointA().getElement());
    newConstraint.getPointB().setEndpoint(originalConstraint.getPointA().getEndpoint());
    newConstraint.getPointB().setAnchor(originalConstraint.getPointA().getAnchor());
    if (originalConstraint.getMaximumBminusA() != null) {
      newConstraint.setMinimumBminusA(originalConstraint.getMaximumBminusA().opposite());
    } else {
      newConstraint.setMinimumBminusA(null);
    }
    if (originalConstraint.getMinimumBminusA() != null) {
      newConstraint.setMaximumBminusA(originalConstraint.getMinimumBminusA().opposite());
    } else {
      newConstraint.setMaximumBminusA(null);
    }

    return newConstraint;
  }

  /**
   * Returns a short description of the type of constraint.
   *
   * @param constraint
   * @param includeThat
   * @return null if the constraint is invalid
   */
  public static String getDescription(BinaryTemporalConstraint constraint, boolean includeThat) {
    Amount<Duration> minimum = constraint.getMinimumBminusA();
    Amount<Duration> maximum = constraint.getMaximumBminusA();
    // construct the string
    if (minimum == null && maximum == null) {
      return null;
    }

    String minimumStr =
        minimum == null ? null : EnsembleAmountFormat.INSTANCE.formatAmount(minimum.abs());
    String maximumStr =
        maximum == null ? null : EnsembleAmountFormat.INSTANCE.formatAmount(maximum.abs());
    String string = "";
    if (minimum == null && maximum != null) {
      // any time after
      if (maximum.approximates(ZERO)) {
        string += "anytime after";
      }
      // at least after
      else if (maximum.isLessThan(ZERO)) {
        string += "at least " + maximumStr + " after";
      }
      // at most before
      else { // max > 0
        string += "at most " + maximumStr + " before";
      }
    } else if (maximum == null && minimum != null) {
      // anytime before
      if (minimum.approximates(ZERO)) {
        string += "anytime before";
      }
      // at most after
      else if (minimum.isLessThan(ZERO)) {
        string += "at most " + minimumStr + " after";
      }
      // at least before
      else { // min > 0
        string += "at least " + minimumStr + " before";
      }
    }
    // at the same time
    else if (minimum != null
        && minimum.approximates(ZERO)
        && maximum != null
        && maximum.approximates(ZERO)) {
      string += "at the same time";
      if (includeThat) {
        if (constraint.getPointB().hasEndpoint()) {
          string += " that";
        } else {
          string += " as";
        }
      }
    }
    // exactly
    else if (minimum != null && minimum.approximates(maximum)) {
      string += "exactly ";
      string += minimumStr;
      if (minimum.isLessThan(ZERO)) {
        string += " after";
      } else { // min > 0
        string += " before";
      }
    }
    // between
    else {
      string += "between ";
      String minAndMaxStr;
      if (maximum != null && minimum != null && minimum.abs().isLessThan(maximum.abs())) {
        minAndMaxStr = minimumStr + " and " + maximumStr;
      } else {
        minAndMaxStr = maximumStr + " and " + minimumStr;
      }
      // after
      if (minimum != null
          && maximum != null
          && !minimum.isGreaterThan(ZERO)
          && !maximum.isGreaterThan(ZERO)) { // min <= 0 && max <= 0
        string += minAndMaxStr;
        string += " after";
      }
      // before
      else if (minimum != null
          && maximum != null
          && !minimum.isLessThan(ZERO)
          && !maximum.isLessThan(ZERO)) { // min >= 0 && max >= 0
        string += minAndMaxStr;
        string += " before";
      }
      // before and after
      else if (minimum != null
          && minimum.isLessThan(ZERO)
          && maximum != null
          && maximum.isGreaterThan(ZERO)) {
        string += maximumStr + " before and " + minimumStr + " after";
      } else {
        return null;
      }
    }
    return string;
  }

  public static List<BinaryTemporalConstraint> convertChainToBinaryTemporalConstraints(
      TemporalChain chain) {
    List<BinaryTemporalConstraint> constraints = new ArrayList<BinaryTemporalConstraint>();
    List<EPlanElement> chainedElements = chain.getElements();
    for (int i = 1; i < chainedElements.size(); i++) {
      EPlanElement a = chainedElements.get(i - 1);
      EPlanElement b = chainedElements.get(i);
      BinaryTemporalConstraint constraint =
          createConstraint(
              a, Timepoint.END, b, Timepoint.START, AmountUtils.exactZero(SI.SECOND), null, "");
      constraints.add(constraint);
    }
    return constraints;
  }

  public static boolean isAnchorable(EStructuralFeature feature) {
    String annotation = EMFUtils.getAnnotation(feature, "constraint", "anchor");
    return Boolean.parseBoolean(annotation);
  }

  /**
   * Utility method that determines if the feature is relevant to the anchor
   *
   * @param point
   * @param planElement
   * @param feature
   * @return
   */
  public static boolean isAnchorPointForElement(
      ConstraintPoint point, EPlanElement planElement, EStructuralFeature feature) {
    return !point.hasEndpoint()
        && point.getElement() == planElement
        && feature.getName().equals(point.getAnchor());
  }

  public static boolean areAnchorsAllowed() {
    return EnsembleProperties.getBooleanPropertyValue("constraint.anchor.allowed", false);
  }

  public static boolean isNested(List<EPlanElement> elements) {
    Set<String> hierarchy = new HashSet();
    for (EPlanElement element : elements) {
      while (element instanceof EPlanChild
          && (((EPlanChild) element).getParent() instanceof EPlanChild)) {
        EPlanElement parent = ((EPlanChild) element).getParent();
        hierarchy.add(parent.getPersistentID());
        element = parent;
      }
    }
    for (EPlanElement element : elements) {
      if (hierarchy.contains(element.getPersistentID())) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns true if all elements have the same parent
   *
   * @param elements
   * @return
   */
  public static boolean sameParent(List<? extends EPlanElement> elements) {
    EObject firstParent = elements.get(0).eContainer();
    for (EPlanElement element : elements) {
      EObject parent = element.eContainer();
      if (firstParent != parent) {
        return false;
      }
    }
    return true;
  }

  public static boolean sameType(List<EPlanElement> elements) {
    Class clazz = null;
    for (EPlanElement element : elements) {
      if (clazz == null) {
        clazz = element.getClass();
      } else if (element.getClass() != clazz) {
        return false;
      }
    }
    return true;
  }
}
  /**
   * Evaluate overall CG
   *
   * @param aircraft
   */
  public void calculateTotalCG(Aircraft aircraft) {

    // Structural CG
    _cgStructure = new CenterOfGravity();

    _cgList.add(aircraft.get_fuselage().get_cg());
    _cgList.add(aircraft.get_wing().get_cg());
    _cgList.add(aircraft.get_HTail().get_cg());
    _cgList.add(aircraft.get_VTail().get_cg());
    _cgList.add(aircraft.get_landingGear().get_cg());
    _cgList.addAll(aircraft.get_theNacelles().get_cgList());

    System.out.println("\n \nCG COMPONENTS LOCATION IN BRF");
    System.out.println("fuselage --> " + _cgList.get(0).get_xBRF());
    System.out.println("wing --> " + _cgList.get(1).get_xBRF());
    System.out.println("HTail --> " + _cgList.get(2).get_xBRF());
    System.out.println("VTail --> " + _cgList.get(3).get_xBRF());
    System.out.println("Landing gear --> " + _cgList.get(4).get_xBRF());
    for (int i = 0; i < aircraft.get_theNacelles().get_cgList().size(); i++) {
      System.out.println("Nacelle  " + i + " --> " + _cgList.get(i + 5).get_xBRF());
    }

    //		 _cgList.forEach(p-> System.out.println(p.get_xBRF()));

    double prod = 0., sum = 0.;
    for (int i = 0; i < _cgList.size(); i++) {

      prod +=
          _cgList.get(i).get_xBRF().getEstimatedValue()
              * aircraft.get_weights().get_massStructureList().get(i).getEstimatedValue();
      sum += aircraft.get_weights().get_massStructureList().get(i).getEstimatedValue();
    }

    _cgStructure.set_xBRF(Amount.valueOf(prod / sum, SI.METER));

    _cgStructure.calculateCGinMAC(
        aircraft.get_wing().get_xLEMacActualBRF(),
        aircraft.get_wing().get_xLEMacActualBRF(),
        Amount.valueOf(0., SI.METER),
        aircraft.get_wing().get_meanAerodChordActual());

    // Structure + engines CG
    _cgStructureAndPower = new CenterOfGravity();

    System.out.println(
        "fuel tank --> " + aircraft.get_theFuelTank().get_cg().get_xBRF().getEstimatedValue());
    double cgPowerPlantContribute = 0.0;

    for (int i = 0; i < aircraft.get_powerPlant().get_engineNumber(); i++) {
      cgPowerPlantContribute =
          cgPowerPlantContribute
              + (aircraft.get_powerPlant().get_cgList().get(i).get_xBRF().getEstimatedValue()
                  * aircraft
                      .get_powerPlant()
                      .get_engineList()
                      .get(i)
                      .get_totalMass()
                      .getEstimatedValue());
      System.out.println(
          "Engine " + i + " --> " + aircraft.get_powerPlant().get_cgList().get(i).get_xBRF());
    }
    _cgStructureAndPower.set_xBRF(
        Amount.valueOf(
            (cgPowerPlantContribute
                    + aircraft.get_weights().get_structuralMass().getEstimatedValue()
                        * get_cgStructure().get_xBRF().getEstimatedValue())
                / (aircraft.get_weights().get_structuralMass().getEstimatedValue()
                    + aircraft.get_powerPlant().get_totalMass().getEstimatedValue()),
            SI.METER));

    get_cgStructureAndPower()
        .calculateCGinMAC(
            aircraft.get_wing().get_xLEMacActualBRF(),
            aircraft.get_wing().get_xLEMacActualBRF(),
            Amount.valueOf(0., SI.METER),
            aircraft.get_wing().get_meanAerodChordActual());

    // MZFW CG location
    _cgMZFM = new CenterOfGravity();

    get_cgMZFM()
        .set_xBRF(
            Amount.valueOf(
                (get_cgStructureAndPower().get_xBRF().getEstimatedValue()
                            * aircraft.get_weights().get_OEM().getEstimatedValue()
                        + aircraft.get_configuration().get_seatsCoG().getEstimatedValue()
                            * aircraft.get_weights().get_paxMassMax().getEstimatedValue())
                    / (aircraft.get_weights().get_paxMassMax().getEstimatedValue()
                        + aircraft.get_weights().get_OEM().getEstimatedValue()),
                SI.METER));

    get_cgMZFM()
        .calculateCGinMAC(
            aircraft.get_wing().get_xLEMacActualBRF(),
            aircraft.get_wing().get_xLEMacActualBRF(),
            Amount.valueOf(0., SI.METER),
            aircraft.get_wing().get_meanAerodChordActual());

    // MTOM CG location
    _cgMTOM = new CenterOfGravity();

    _cgMTOM.set_xBRF(
        Amount.valueOf(
            (_cgMZFM.get_xBRF().getEstimatedValue()
                        * aircraft.get_weights().get_MZFM().getEstimatedValue()
                    + aircraft.get_theFuelTank().get_fuelMass().getEstimatedValue()
                        * aircraft.get_theFuelTank().get_cg().get_xBRF().getEstimatedValue())
                / aircraft.get_weights().get_MTOM().getEstimatedValue(),
            SI.METER));

    _cgMTOM.calculateCGinMAC(
        aircraft.get_wing().get_xLEMacActualBRF(),
        aircraft.get_wing().get_xLEMacActualBRF(),
        Amount.valueOf(0., SI.METER),
        aircraft.get_wing().get_meanAerodChordActual());
  }
public class Aerodynamics extends AuxiliaryComponentCalculator {

  private String _id = "";
  public static int idCounter = 0;
  public static int nAero = 0;

  private CalculateMachCr calculateMachCr;
  private CalculateCdWaveDrag calculateCdWaveDrag;
  private double _mach;
  private double _clCurrent, _clCurrentViscid;

  /** The angle of attack of lifting surface chord root */
  private Amount<Angle> _alphaRoot;

  /** Zero lift angle of attack */
  private Amount<Angle> _alphaZeroLift = Amount.valueOf(0, SI.RADIAN);

  /** End of linear region of lift vs alpha curve */
  private Amount<Angle> _alphaStar = Amount.valueOf(0, SI.RADIAN); // end-of-linearity

  /** Stall angle */
  private Amount<Angle> _alphaStall = Amount.valueOf(0, SI.RADIAN);

  /** Current angle of attack */
  private Amount<Angle> _alphaCurrent;

  /** The actual angle of attack of the airfoil */
  private Amount<Angle> _alphaEffective = Amount.valueOf(0, SI.RADIAN);

  private Double _clAtAlpha0;
  private Amount<?> _clAlpha;
  private Double _clStar;
  private Double _clMax;
  private Double _cdMin;
  private Double _clAtCdMin;
  private Double _kFactorDragPolar;
  private Double _mExponentPolar;
  private Double _mExponentDragPolar;
  private Double _machCr0;
  private static Map<AirfoilEnum, Double> _kWaveDragMap = new HashMap<AirfoilEnum, Double>();
  private Double _aerodynamicCenterX;
  private Double _cmAC;
  private Double _cmACStall;
  private Double _cmAlphaAC;
  private double _machCr, _cdw = 0., _machCurrent;
  private Geometry geometry;
  private Airfoil _theAirfoil;
  private double[] clAirfoil;

  MyArray alphaArray = new MyArray();

  /*
   * This constructor builds the airfoil aerodynamics using the AirfoilCreator class
   */
  public Aerodynamics(AirfoilCreator airfoilCreator) {

    _alphaZeroLift = airfoilCreator.getAlphaZeroLift();
    _clAtAlpha0 = airfoilCreator.getClAtAlphaZero();
    _clAlpha = airfoilCreator.getClAlphaLinearTrait();
    _alphaStar = airfoilCreator.getAlphaEndLinearTrait();
    _clStar = airfoilCreator.getClEndLinearTrait();
    _alphaStall = airfoilCreator.getAlphaStall();
    _clMax = airfoilCreator.getClMax();
    _cdMin = airfoilCreator.getCdMin();
    _clAtCdMin = airfoilCreator.getClAtCdMin();
    _kFactorDragPolar = airfoilCreator.getKFactorDragPolar();
    _aerodynamicCenterX = airfoilCreator.getXACNormalized();
    _cmAC = airfoilCreator.getCmAC();
    _cmACStall = airfoilCreator.getCmACAtStall();
    _cmAlphaAC = airfoilCreator.getCmAlphaQuarterChord();
    _mExponentPolar = airfoilCreator.getMExponentDragPolar();

    calculateMachCr = new CalculateMachCr();
    calculateCdWaveDrag = new CalculateCdWaveDrag();
  }

  public Aerodynamics(Airfoil airf, AircraftEnum aircraftName, AirfoilStationEnum station) {
    switch (aircraftName) {
      case ATR72:
        switch (station) {
          case ROOT:
            initializeAerodynamics(airf, AirfoilEnum.NACA23_018);
            break;
          case KINK:
            initializeAerodynamics(airf, AirfoilEnum.NACA23_018);
            break;
          case TIP:
            initializeAerodynamics(airf, AirfoilEnum.NACA23_015);
            break;
        }
        break;
      case B747_100B:
        // TODO implement this
        switch (station) {
          case ROOT:
            initializeAerodynamics(airf, AirfoilEnum.NACA65_209);
            break;
          case KINK:
            initializeAerodynamics(airf, AirfoilEnum.NACA65_209);
            break;
          case TIP:
            initializeAerodynamics(airf, AirfoilEnum.NACA65_206);
            break;
        }
        break;

      case AGILE_DC1:
        switch (station) {
          case ROOT:
            initializeAerodynamics(airf, AirfoilEnum.DFVLR_R4);
            // TODO: It should be Ha5 airfoil
            break;
          case KINK:
            initializeAerodynamics(airf, AirfoilEnum.DFVLR_R4);
            break;
          case TIP:
            initializeAerodynamics(airf, AirfoilEnum.DFVLR_R4);
            break;
        }
    }
  }

  public Aerodynamics(Airfoil airfoil, AirfoilEnum airfoilName) {

    initializeAerodynamics(airfoil, airfoilName);
  }

  private void initializeAerodynamics(Airfoil airf, AirfoilEnum airfoilName) {
    switch (airfoilName) {
      case NACA23_018:
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;
        airf.setName(AirfoilEnum.NACA23_018);
        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.2), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(9.5), SI.RADIAN); // end-of-linearity
        _clStar = 1.3;
        _alphaStall = Amount.valueOf(Math.toRadians(16.0), SI.RADIAN);
        _clMax = 1.65; // 1.8;

        _cdMin = 0.00675;
        _clAtCdMin = 0.3;
        _kFactorDragPolar = 0.004;

        _aerodynamicCenterX = 0.243;
        _cmAC = -0.02;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA23_015:
        airf.setName(AirfoilEnum.NACA23_015);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.1), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(10), SI.RADIAN); // end-of-linearity
        _clStar = 1.2;
        _alphaStall = Amount.valueOf(Math.toRadians(18.0), SI.RADIAN);
        _clMax = 1.7; // 1.6;

        _cdMin = 0.00625;
        _clAtCdMin = 0.1;
        _kFactorDragPolar = 0.004;
        _aerodynamicCenterX = 0.243;
        _cmAC = -0.02;
        _cmACStall = -0.07;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA23_012:
        airf.setName(AirfoilEnum.NACA23_012);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.32), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(14), SI.RADIAN); // end-of-linearity
        _clStar = 1.6;
        _alphaStall = Amount.valueOf(Math.toRadians(18), SI.RADIAN);
        _clMax = 1.8; // 1.5;

        _cdMin = 0.00575;
        _clAtCdMin = 0.23;
        _kFactorDragPolar = 0.004;

        _aerodynamicCenterX = 0.247;
        _cmAC = -0.03;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA65_209:
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.3), SI.RADIAN);
        _clAlpha = Amount.valueOf(5.96, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(11), SI.RADIAN); // end-of-linearity
        _clStar = 1.1;
        _alphaStall = Amount.valueOf(Math.toRadians(17.0), SI.RADIAN);
        _clMax = 1.6;

        _cdMin = 0.025;
        _clAtCdMin = 0.2;
        _kFactorDragPolar = 0.0035;

        _aerodynamicCenterX = 0.25;
        _cmAC = -0.07;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA65_206:
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.4), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.13, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(10.0), SI.RADIAN); // end-of-linearity
        _clStar = _clAlpha.getEstimatedValue() * _alphaStar.getEstimatedValue();
        _alphaStall = Amount.valueOf(Math.toRadians(15.0), SI.RADIAN);
        _clMax = 1.3;

        _cdMin = 0.025;
        _clAtCdMin = 0.2;
        _kFactorDragPolar = 0.0035;

        _aerodynamicCenterX = 0.25;
        _cmAC = -0.07;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA0012:
        airf.setName(AirfoilEnum.NACA0012);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(0), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.92, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(11), SI.RADIAN); // end-of-linearity
        _clStar = 1.23;
        _alphaStall = Amount.valueOf(Math.toRadians(20.1), SI.RADIAN);
        _clMax = 1.86; // 1.5;

        _cdMin = 0.0055;
        _clAtCdMin = 0.0;
        _kFactorDragPolar = 0.0035;

        _aerodynamicCenterX = 0.25;
        _cmAC = 0.0;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case DFVLR_R4:
        airf.setName(AirfoilEnum.DFVLR_R4);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-3.75), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(11), SI.RADIAN); // end-of-linearity
        _clStar = 1.53;
        _alphaStall = Amount.valueOf(Math.toRadians(16.75), SI.RADIAN);
        _clMax = 1.7671; // 1.5;

        _cdMin = 0.0056;
        _clAtCdMin = 0.0;
        _kFactorDragPolar = 0.075;

        _aerodynamicCenterX = 0.25;
        _cmAC = -0.1168;
        _cmACStall = -0.0515;
        _cmAlphaAC = 0.0015;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;
      default:
        break;
    }
  }

  public double calculateClAtAlphaLinear(Double alpha) {
    _clCurrent = alpha / _clAlpha.getEstimatedValue();
    return _clCurrent;
  }

  /**
   * This function calculates Cl at alpha of an airfoil. It calculates both in the linear trait and
   * non linear using a cubic interpolation
   *
   * @author Manuela Ruocco
   * @param double alpha: angle of attack in radians
   */
  public double calculateClAtAlpha(double alpha) {

    //		double clActual= MyMathUtils.getInterpolatedValue1DLinear(alphaArray.toArray(), clAirfoil,
    // alpha);
    //		return clActual;
    double q = _clStar - _clAlpha.getEstimatedValue() * _alphaStar.getEstimatedValue();
    if (alpha < _alphaStar.getEstimatedValue()) {
      _clCurrentViscid = _clAlpha.getEstimatedValue() * alpha + q;
    } else {
      double[][] matrixData = {
        {
          Math.pow(_alphaStall.getEstimatedValue(), 3),
          Math.pow(_alphaStall.getEstimatedValue(), 2),
          _alphaStall.getEstimatedValue(),
          1.0
        },
        {
          3 * Math.pow(_alphaStall.getEstimatedValue(), 2),
          2 * _alphaStall.getEstimatedValue(),
          1.0,
          0.0
        },
        {
          3 * Math.pow(_alphaStar.getEstimatedValue(), 2),
          2 * _alphaStar.getEstimatedValue(),
          1.0,
          0.0
        },
        {
          Math.pow(_alphaStar.getEstimatedValue(), 3),
          Math.pow(_alphaStar.getEstimatedValue(), 2),
          _alphaStar.getEstimatedValue(),
          1.0
        }
      };
      RealMatrix m = MatrixUtils.createRealMatrix(matrixData);
      double[] vector = {_clMax, 0, _clAlpha.getEstimatedValue(), _clStar};
      double[] solSystem = MyMathUtils.solveLinearSystem(m, vector);
      double a = solSystem[0];
      double b = solSystem[1];
      double c = solSystem[2];
      double d = solSystem[3];

      _clCurrentViscid = a * Math.pow(alpha, 3) + b * Math.pow(alpha, 2) + c * alpha + d;
    }
    return _clCurrentViscid;
  }

  public double calculateClAtAlphaInterp(double alpha) {

    double clActual =
        MyMathUtils.getInterpolatedValue1DLinear(alphaArray.toArray(), clAirfoil, alpha);
    return clActual;
  }

  public void calculateClvsAlpha() {

    int nValue = 50;
    double alphaMin = Math.toRadians(-5);
    double alphaMax = Math.toRadians(25);
    alphaArray.linspace(alphaMin, alphaMax, nValue);
    double alpha;
    double q = _clStar - _clAlpha.getEstimatedValue() * _alphaStar.getEstimatedValue();
    clAirfoil = new double[nValue];
    for (int i = 0; i < nValue; i++) {

      alpha = alphaArray.get(i);
      if (alpha < _alphaStar.getEstimatedValue()) {
        clAirfoil[i] = _clAlpha.getEstimatedValue() * alpha + q;
      } else {
        double[][] matrixData = {
          {
            Math.pow(_alphaStall.getEstimatedValue(), 3),
            Math.pow(_alphaStall.getEstimatedValue(), 2),
            _alphaStall.getEstimatedValue(),
            1.0
          },
          {
            3 * Math.pow(_alphaStall.getEstimatedValue(), 2),
            2 * _alphaStall.getEstimatedValue(),
            1.0,
            0.0
          },
          {
            3 * Math.pow(_alphaStar.getEstimatedValue(), 2),
            2 * _alphaStar.getEstimatedValue(),
            1.0,
            0.0
          },
          {
            Math.pow(_alphaStar.getEstimatedValue(), 3),
            Math.pow(_alphaStar.getEstimatedValue(), 2),
            _alphaStar.getEstimatedValue(),
            1.0
          }
        };
        RealMatrix m = MatrixUtils.createRealMatrix(matrixData);
        double[] vector = {_clMax, 0, _clAlpha.getEstimatedValue(), _clStar};
        double[] solSystem = MyMathUtils.solveLinearSystem(m, vector);
        double a = solSystem[0];
        double b = solSystem[1];
        double c = solSystem[2];
        double d = solSystem[3];

        clAirfoil[i] = a * Math.pow(alpha, 3) + b * Math.pow(alpha, 2) + c * alpha + d;
      }
    }
  }

  public void plotClvsAlpha(String subfolderPath, String name) {

    System.out.println("\n \n-----------------------------------------------------");
    System.out.println("STARTING PLOT AIRFOIL CL vs ALPHA CURVE " + name);
    System.out.println("-----------------------------------------------------");

    MyArray alphaArray = new MyArray();
    int _numberOfAlpha = 60;
    double[] clArray = new double[_numberOfAlpha];
    double[] alphaArrayDeg = new double[_numberOfAlpha];

    Amount<Angle> alphaActualAmount;
    Amount<Angle> alphaStart = Amount.valueOf(toRadians(-6.), SI.RADIAN);
    Amount<Angle> alphaEnd = Amount.valueOf(toRadians(25.0), SI.RADIAN);

    alphaArray.setDouble(
        MyArrayUtils.linspace(
            alphaStart.getEstimatedValue(), alphaEnd.getEstimatedValue(), _numberOfAlpha));

    for (int i = 0; i < _numberOfAlpha; i++) {
      alphaActualAmount = Amount.valueOf(alphaArray.get(i), SI.RADIAN);
      clArray[i] = calculateClAtAlpha(alphaActualAmount.getEstimatedValue());
      alphaArrayDeg[i] = alphaActualAmount.to(NonSI.DEGREE_ANGLE).getEstimatedValue();
    }

    MyChartToFileUtils.plotNoLegend(
        alphaArrayDeg,
        clArray,
        null,
        null,
        null,
        null,
        "alpha",
        "CL",
        "deg",
        "",
        subfolderPath,
        "CL vs alpha Airfoil" + name);

    System.out.println("-----------------------------------------------------");
    System.out.println("\n DONE");
    System.out.println("-----------------------------------------------------");
  }

  /** Evaluate Cl at effective AoA (i.e., taking into account airfoil twist) */
  public void calculateClAtAlphaEffective() {
    calculateClAtAlphaLinear(calculateAlphaEffective());
  }

  /** Evaluate effective AoA (i.e., taking into account airfoil twist) */
  public double calculateAlphaEffective() {
    _alphaEffective =
        Amount.valueOf(
            geometry.get_twist().getEstimatedValue() + _alphaRoot.getEstimatedValue(), SI.RADIAN);

    return _alphaEffective.getEstimatedValue();
  }

  /**
   * Evaluate Cd using a parabolic polar curve
   *
   * @author Manuela Ruocco
   */
  public double calculateCdAtAlpha(Amount<Angle> alpha) {
    double cdAirfoil;
    double clAirfoil = calculateClAtAlpha(alpha.getEstimatedValue());
    cdAirfoil = get_cdMin() + Math.pow((clAirfoil - get_clAtCdMin()), 2) * get_kFactorDragPolar();
    return cdAirfoil;
  }

  public double calculateCdAtClLinear(double cl) {
    double qValue = _clStar - _clAlpha.getEstimatedValue() * _alphaStar.getEstimatedValue();
    Amount<Angle> alpha;
    double alphaTemp;
    alphaTemp = (cl - qValue) / _clAlpha.getEstimatedValue();

    alpha = Amount.valueOf(alphaTemp, SI.RADIAN);

    double cdAirfoil = calculateCdAtAlpha(alpha);
    return cdAirfoil;
  }

  /**
   * Evaluate Cd using a parabolic polar curve
   *
   * @author Manuela Ruocco
   */
  public static double calculateCd(
      double clAirfoil, Double cdMin, Double clAtCdMin, double kFactorDragPolar) {
    double cdAirfoil;
    cdAirfoil = cdMin + Math.pow((clAirfoil - clAtCdMin), 2) * kFactorDragPolar;
    return cdAirfoil;
  }

  /**
   * This function plots the airfoil drag polar using a parabolic approssimation.
   *
   * @author Manuela Ruocco
   */
  public void plotPolar() {
    System.out.println("\n \n-----------------------------------------------------");
    System.out.println("STARTING PLOT AIRFOIL DRAG POLAR");
    System.out.println("-----------------------------------------------------");

    MyArray alphaArray = new MyArray();
    int _numberOfAlpha = 40;
    double[] cdArrayPolar = new double[_numberOfAlpha];
    double[] clArrayPolar = new double[_numberOfAlpha];
    Amount<Angle> alphaActualAmount;

    Amount<Angle> alphaStart = Amount.valueOf(toRadians(-6.), SI.RADIAN);
    Amount<Angle> alphaEnd = Amount.valueOf(toRadians(12.), SI.RADIAN);

    alphaArray.setDouble(
        MyArrayUtils.linspace(
            alphaStart.getEstimatedValue(), alphaEnd.getEstimatedValue(), _numberOfAlpha));

    String folderPathPolar =
        MyConfiguration.currentDirectoryString + File.separator + "out" + File.separator;
    String subfolderPathPolar =
        JPADStaticWriteUtils.createNewFolder(folderPathPolar + "Polar_Airfoil" + File.separator);

    for (int i = 0; i < _numberOfAlpha; i++) {
      alphaActualAmount = Amount.valueOf(alphaArray.get(i), SI.RADIAN);
      clArrayPolar[i] = calculateClAtAlpha(alphaActualAmount.getEstimatedValue());
      cdArrayPolar[i] = calculateCdAtAlpha(alphaActualAmount);
    }

    MyChartToFileUtils.plotNoLegend(
        cdArrayPolar,
        clArrayPolar,
        null,
        null,
        null,
        null,
        "Cd",
        "Cl",
        "",
        "",
        subfolderPathPolar,
        "Polar_Airfoil ");

    System.out.println("\n \n-----------------------------------------------------");
    System.out.println("DONE");
    System.out.println("-----------------------------------------------------");
  }

  public class CalculateMachCr {

    private double mCr0PerkinsAndHage() {
      // Page 407 Sforza
      _machCr0 = 0.89 - 1.3 * (geometry.get_maximumThicknessOverChord());
      return _machCr0;
    }

    private double mCr0Shevell() {
      // Page 409 Sforza
      _machCr0 = 0.9 - geometry.get_maximumThicknessOverChord();
      return _machCr0;
    }

    public double perkinsAndHage() {
      if (_kWaveDragMap.containsKey(_theAirfoil.getFamily())) {
        _machCr = mCr0PerkinsAndHage() - _kWaveDragMap.get(_theAirfoil.getFamily()) * _clCurrent;
      } else _machCr = 0.;
      return _machCr;
    }

    public double shevell() {
      _machCr = mCr0Shevell() - (0.17 + 0.016) * _clCurrent;
      return _machCr;
    }

    public double korn() {
      double k;
      if (_theAirfoil.getType().equals(AirfoilTypeEnum.CONVENTIONAL)) k = 0.87;
      else k = 0.95;

      _machCr = (k - 0.108) - geometry.get_maximumThicknessOverChord() - 0.1 * _clCurrent;
      return _machCr;
    }

    public void allMethods() {
      perkinsAndHage();
      shevell();
      korn();
    }
  }

  public class CalculateCdWaveDrag {

    public double perkinsAndHage() {

      // Difference between current mach number and critical mach number
      double diff = _machCurrent - calculateMachCr.perkinsAndHage();

      if (diff > 0) _cdw = 9.5 * Math.pow((diff), 2.8) + 0.00193;
      return _cdw;
    }

    /** Page 410 Sforza */
    public double lockShevell() {

      double diff = _machCurrent - calculateMachCr.shevell();

      if (diff > 0) _cdw = 20 * Math.pow((diff), 4);
      return _cdw;
    }

    public double lockKorn() {

      double diff = _machCurrent - calculateMachCr.korn();

      if (diff > 0) _cdw = 20 * Math.pow((diff), 4);
      return _cdw;
    }

    public void allMethods() {
      perkinsAndHage();
      lockShevell();
      lockKorn();
    }
  }

  public CalculateMachCr getCalculateMachCr() {
    return calculateMachCr;
  }

  public CalculateCdWaveDrag getCalculateCdWaveDrag() {
    return calculateCdWaveDrag;
  }

  public double get_mach() {
    return _mach;
  }

  public void set_mach(double _mach) {
    this._mach = _mach;
  }

  public double get_clCurrent() {
    return _clCurrent;
  }

  public void set_clCurrent(double _clCurrent) {
    this._clCurrent = _clCurrent;
  }

  public Amount<Angle> get_alphaRoot() {
    return _alphaRoot;
  }

  public void set_alphaRoot(Amount<Angle> _alphaRoot) {
    this._alphaRoot = _alphaRoot;
  }

  public Amount<Angle> get_alphaZeroLift() {
    return _alphaZeroLift;
  }

  public void set_alphaZeroLift(Amount<Angle> _alphaZeroLift) {
    this._alphaZeroLift = _alphaZeroLift;
  }

  public Amount<Angle> get_alphaStar() {
    return _alphaStar;
  }

  public void set_alphaStar(Amount<Angle> _alphaStar) {
    this._alphaStar = _alphaStar;
  }

  public Amount<Angle> get_alphaStall() {
    return _alphaStall;
  }

  public void set_alphaStall(Amount<Angle> _alphaStall) {
    this._alphaStall = _alphaStall;
  }

  public Amount<Angle> get_alphaCurrent() {
    return _alphaCurrent;
  }

  public void set_alphaCurrent(Amount<Angle> _alphaCurrent) {
    this._alphaCurrent = _alphaCurrent;
  }

  public Amount<Angle> get_alphaEffective() {
    return _alphaEffective;
  }

  public void set_alphaEffective(Amount<Angle> _alphaEffective) {
    this._alphaEffective = _alphaEffective;
  }

  public Double get_clAtAlpha0() {
    return _clAtAlpha0;
  }

  public void set_clAtAlpha0(Double _clAtAlpha0) {
    this._clAtAlpha0 = _clAtAlpha0;
  }

  public Amount<?> getClAlpha() {
    return _clAlpha;
  }

  public void set_clAlpha(Amount<?> _clAlpha) {
    this._clAlpha = _clAlpha;
  }

  public Double get_clStar() {
    return _clStar;
  }

  public void set_clStar(Double _clStar) {
    this._clStar = _clStar;
  }

  public Double get_clMax() {
    return _clMax;
  }

  public void set_clMax(Double _clMax) {
    this._clMax = _clMax;
  }

  public Double get_cdMin() {
    return _cdMin;
  }

  public void set_cdMin(Double _cdMin) {
    this._cdMin = _cdMin;
  }

  public Double get_clAtCdMin() {
    return _clAtCdMin;
  }

  public void set_clAtCdMin(Double _clAtCdMin) {
    this._clAtCdMin = _clAtCdMin;
  }

  public Double get_kFactorDragPolar() {
    return _kFactorDragPolar;
  }

  public void set_kFactorDragPolar(Double _kFactorDragPolar) {
    this._kFactorDragPolar = _kFactorDragPolar;
  }

  public Double get_mExponentDragPolar() {
    return _mExponentDragPolar;
  }

  public void set_mExponentDragPolar(Double _mExponentDragPolar) {
    this._mExponentDragPolar = _mExponentDragPolar;
  }

  public Double get_machCr0() {
    return _machCr0;
  }

  public void set_machCr0(Double _machCr0) {
    this._machCr0 = _machCr0;
  }

  public Double get_aerodynamicCenterX() {
    return _aerodynamicCenterX;
  }

  public void set_aerodynamicCenterX(Double _aerodynamicCenterX) {
    this._aerodynamicCenterX = _aerodynamicCenterX;
  }

  public Double get_cmAC() {
    return _cmAC;
  }

  public void set_cmAC(Double _cmAC) {
    this._cmAC = _cmAC;
  }

  public Double get_cmACStall() {
    return _cmACStall;
  }

  public void set_cmACStall(Double _cmACStall) {
    this._cmACStall = _cmACStall;
  }

  public Double get_cmAlphaAC() {
    return _cmAlphaAC;
  }

  public void set_cmAlphaAC(Double _cmAlphaAC) {
    this._cmAlphaAC = _cmAlphaAC;
  }

  public double get_machCr() {
    return _machCr;
  }

  public void set_machCr(double _machCr) {
    this._machCr = _machCr;
  }

  public double get_cdw() {
    return _cdw;
  }

  public void set_cdw(double _cdw) {
    this._cdw = _cdw;
  }

  public double get_machCurrent() {
    return _machCurrent;
  }

  public void set_machCurrent(double _machCurrent) {
    this._machCurrent = _machCurrent;
  }

  public static Map<AirfoilEnum, Double> get_kWaveDragMap() {
    return _kWaveDragMap;
  }

  @Override
  public String getId() {
    return _id;
  }

  public String getIdNew() {
    String id = _theAirfoil.getId() + "aero" + nAero;
    nAero++;
    return id;
  }

  public double[] getClAirfoil() {
    return clAirfoil;
  }

  public void setClAirfoil(double[] clAirfoil) {
    this.clAirfoil = clAirfoil;
  }

  public MyArray getAlphaArray() {
    return alphaArray;
  }

  public void setAlphaArray(MyArray alphaArray) {
    this.alphaArray = alphaArray;
  }

  public Double get_mExponentPolar() {
    return _mExponentPolar;
  }

  public void set_mExponentPolar(Double _mExponentPolar) {
    this._mExponentPolar = _mExponentPolar;
  }
}
  private void initializeAerodynamics(Airfoil airf, AirfoilEnum airfoilName) {
    switch (airfoilName) {
      case NACA23_018:
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;
        airf.setName(AirfoilEnum.NACA23_018);
        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.2), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(9.5), SI.RADIAN); // end-of-linearity
        _clStar = 1.3;
        _alphaStall = Amount.valueOf(Math.toRadians(16.0), SI.RADIAN);
        _clMax = 1.65; // 1.8;

        _cdMin = 0.00675;
        _clAtCdMin = 0.3;
        _kFactorDragPolar = 0.004;

        _aerodynamicCenterX = 0.243;
        _cmAC = -0.02;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA23_015:
        airf.setName(AirfoilEnum.NACA23_015);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.1), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(10), SI.RADIAN); // end-of-linearity
        _clStar = 1.2;
        _alphaStall = Amount.valueOf(Math.toRadians(18.0), SI.RADIAN);
        _clMax = 1.7; // 1.6;

        _cdMin = 0.00625;
        _clAtCdMin = 0.1;
        _kFactorDragPolar = 0.004;
        _aerodynamicCenterX = 0.243;
        _cmAC = -0.02;
        _cmACStall = -0.07;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA23_012:
        airf.setName(AirfoilEnum.NACA23_012);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.32), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(14), SI.RADIAN); // end-of-linearity
        _clStar = 1.6;
        _alphaStall = Amount.valueOf(Math.toRadians(18), SI.RADIAN);
        _clMax = 1.8; // 1.5;

        _cdMin = 0.00575;
        _clAtCdMin = 0.23;
        _kFactorDragPolar = 0.004;

        _aerodynamicCenterX = 0.247;
        _cmAC = -0.03;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA65_209:
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.3), SI.RADIAN);
        _clAlpha = Amount.valueOf(5.96, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(11), SI.RADIAN); // end-of-linearity
        _clStar = 1.1;
        _alphaStall = Amount.valueOf(Math.toRadians(17.0), SI.RADIAN);
        _clMax = 1.6;

        _cdMin = 0.025;
        _clAtCdMin = 0.2;
        _kFactorDragPolar = 0.0035;

        _aerodynamicCenterX = 0.25;
        _cmAC = -0.07;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA65_206:
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-1.4), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.13, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(10.0), SI.RADIAN); // end-of-linearity
        _clStar = _clAlpha.getEstimatedValue() * _alphaStar.getEstimatedValue();
        _alphaStall = Amount.valueOf(Math.toRadians(15.0), SI.RADIAN);
        _clMax = 1.3;

        _cdMin = 0.025;
        _clAtCdMin = 0.2;
        _kFactorDragPolar = 0.0035;

        _aerodynamicCenterX = 0.25;
        _cmAC = -0.07;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case NACA0012:
        airf.setName(AirfoilEnum.NACA0012);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(0), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.92, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(11), SI.RADIAN); // end-of-linearity
        _clStar = 1.23;
        _alphaStall = Amount.valueOf(Math.toRadians(20.1), SI.RADIAN);
        _clMax = 1.86; // 1.5;

        _cdMin = 0.0055;
        _clAtCdMin = 0.0;
        _kFactorDragPolar = 0.0035;

        _aerodynamicCenterX = 0.25;
        _cmAC = 0.0;
        _cmACStall = -0.09;
        _cmAlphaAC = 0.;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;

      case DFVLR_R4:
        airf.setName(AirfoilEnum.DFVLR_R4);
        _id = airf.getId() + "1" + idCounter + "99";
        idCounter++;

        _theAirfoil = airf;
        geometry = airf.getGeometry();

        _alphaZeroLift = Amount.valueOf(Math.toRadians(-3.75), SI.RADIAN);
        _clAlpha = Amount.valueOf(6.3, SI.RADIAN.inverse());
        _alphaStar = Amount.valueOf(Math.toRadians(11), SI.RADIAN); // end-of-linearity
        _clStar = 1.53;
        _alphaStall = Amount.valueOf(Math.toRadians(16.75), SI.RADIAN);
        _clMax = 1.7671; // 1.5;

        _cdMin = 0.0056;
        _clAtCdMin = 0.0;
        _kFactorDragPolar = 0.075;

        _aerodynamicCenterX = 0.25;
        _cmAC = -0.1168;
        _cmACStall = -0.0515;
        _cmAlphaAC = 0.0015;
        calculateMachCr = new CalculateMachCr();
        calculateCdWaveDrag = new CalculateCdWaveDrag();
        break;
      default:
        break;
    }
  }
Example #11
0
public class Finocyl extends ExtrudedShapeGrain implements Validating {
  private Amount<Length> oD = Amount.valueOf(30, SI.MILLIMETER);
  private Amount<Length> iD = Amount.valueOf(10, SI.MILLIMETER);
  private Amount<Length> finWidth = Amount.valueOf(2, SI.MILLIMETER);
  private Amount<Length> finDiameter = Amount.valueOf(20, SI.MILLIMETER);
  private int finCount = 5;

  public Finocyl() {
    try {
      setLength(Amount.valueOf(70, SI.MILLIMETER));
    } catch (PropertyVetoException e) {
      e.printStackTrace();
    }
    generateGeometry();
  }

  private void generateGeometry() {
    double odmm = oD.doubleValue(SI.MILLIMETER);
    double idmm = iD.doubleValue(SI.MILLIMETER);
    double fwmm = finWidth.doubleValue(SI.MILLIMETER);
    double fdmm = finDiameter.doubleValue(SI.MILLIMETER);

    xsection = new BurningShape();
    Shape outside = new Ellipse2D.Double(-odmm / 2, -odmm / 2, odmm, odmm);
    xsection.add(outside);
    xsection.inhibit(outside);
    xsection.subtract(new Ellipse2D.Double(-idmm / 2, -idmm / 2, idmm, idmm));
    webThickness = null;

    for (int i = 0; i < finCount; i++) {
      Shape fin = new Rectangle2D.Double(-fwmm / 2, 0, fwmm, fdmm / 2);
      xsection.subtract(fin, AffineTransform.getRotateInstance(i * (2.0 * Math.PI / finCount)));
    }
  }

  public Amount<Length> getOD() {
    return oD;
  }

  public void setOD(Amount<Length> od) throws PropertyVetoException {
    if (od.equals(this.oD)) return;
    this.oD = od;
    generateGeometry();
  }

  public Amount<Length> getID() {
    return iD;
  }

  public void setID(Amount<Length> id) throws PropertyVetoException {
    if (id.equals(this.iD)) return;
    iD = id;
    generateGeometry();
  }

  public Amount<Length> getFinWidth() {
    return finWidth;
  }

  public void setFinWidth(Amount<Length> finWidth) throws PropertyVetoException {
    if (finWidth.equals(this.finWidth)) return;
    this.finWidth = finWidth;
    generateGeometry();
  }

  public Amount<Length> getFinDiameter() {
    return finDiameter;
  }

  public void setFinDiameter(Amount<Length> finDiameter) throws PropertyVetoException {
    if (finDiameter.equals(this.finDiameter)) return;
    this.finDiameter = finDiameter;
    generateGeometry();
  }

  public int getFinCount() {
    return finCount;
  }

  public void setFinCount(int finCount) throws PropertyVetoException {
    if (finCount == this.finCount) return;
    this.finCount = finCount;
    generateGeometry();
  }

  @Override
  public void validate() throws ValidationException {
    if (iD.equals(Amount.ZERO)) throw new ValidationException(this, "Invalid iD");
    if (oD.equals(Amount.ZERO)) throw new ValidationException(this, "Invalid oD");
    if (getLength().equals(Amount.ZERO)) throw new ValidationException(this, "Invalid Length");
    if (iD.isGreaterThan(oD)) throw new ValidationException(this, "iD > oD");
  }
}