/**
   * 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 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 static List<Double> calcCmDistributionLiftingSurfaceWithIntegral(
      NasaBlackwell theNasaBlackwellCalculator,
      Amount<Angle> angleOfAttack,
      List<Amount<Length>> liftingSurfaceDimensionalY,
      List<Double> liftingSurfaceCl0Distribution, // all distributions must have the same length!!
      List<Double> liftingSurfaceCLAlphaDegDistribution,
      List<Double> liftingSurfaceCmACDistribution,
      List<Double> liftingSurfaceXACadimensionalDistribution,
      List<Amount<Length>> liftingSurfaceChordDistribution,
      List<Amount<Length>> liftingSurfaceXLEDistribution,
      List<List<Double>>
          airfoilClMatrix, // this is a list of list. each list is referred to an airfoil along the
      // semispan
      List<Amount<Angle>>
          anglesOfAttackClMatrix, // references angle of attack of the list of list airfoilClMatrix
      Amount<Length> momentumPole // referred to the origin of LRF
      ) {

    List<Double> cmDistribution = new ArrayList<>();

    double[] distancesArrayAC,
        clDistribution,
        alphaDistribution,
        clInducedDistributionAtAlphaNew,
        xcPfracC;
    int numberOfPointSemiSpanWise = liftingSurfaceCl0Distribution.size();

    clDistribution = new double[numberOfPointSemiSpanWise];
    alphaDistribution = new double[numberOfPointSemiSpanWise];
    clInducedDistributionAtAlphaNew = new double[numberOfPointSemiSpanWise];
    distancesArrayAC = new double[numberOfPointSemiSpanWise];
    xcPfracC = new double[numberOfPointSemiSpanWise];

    theNasaBlackwellCalculator.calculate(angleOfAttack);
    clDistribution = theNasaBlackwellCalculator.getClTotalDistribution().toArray();

    for (int ii = 0; ii < numberOfPointSemiSpanWise; ii++) {
      alphaDistribution[ii] =
          (clDistribution[ii] - liftingSurfaceCl0Distribution.get(ii))
              / liftingSurfaceCLAlphaDegDistribution.get(ii);

      if (alphaDistribution[ii] < angleOfAttack.doubleValue(NonSI.DEGREE_ANGLE)) {
        clInducedDistributionAtAlphaNew[ii] =
            liftingSurfaceCLAlphaDegDistribution.get(ii) * alphaDistribution[ii]
                + liftingSurfaceCl0Distribution.get(ii);
      } else {
        clInducedDistributionAtAlphaNew[ii] =
            MyMathUtils.getInterpolatedValue1DLinear(
                MyArrayUtils.convertListOfAmountTodoubleArray(anglesOfAttackClMatrix),
                MyArrayUtils.convertToDoublePrimitive(
                    MyArrayUtils.convertListOfDoubleToDoubleArray(airfoilClMatrix.get(ii))),
                alphaDistribution[ii]);
      }

      xcPfracC[ii] =
          liftingSurfaceXACadimensionalDistribution.get(ii)
              - (liftingSurfaceCmACDistribution.get(ii) / clInducedDistributionAtAlphaNew[ii]);

      distancesArrayAC[ii] =
          momentumPole.doubleValue(SI.METER)
              - (liftingSurfaceXLEDistribution.get(ii).doubleValue(SI.METER)
                  + (xcPfracC[ii] * liftingSurfaceChordDistribution.get(ii).doubleValue(SI.METER)));

      cmDistribution.add(
          ii,
          clInducedDistributionAtAlphaNew[ii]
              * (distancesArrayAC[ii]
                  / liftingSurfaceChordDistribution.get(ii).doubleValue(SI.METER)));
    }
    cmDistribution.set(numberOfPointSemiSpanWise - 1, 0.);
    return cmDistribution;
  }
  public static List<Double> calcCMLiftingSurfaceWithIntegralACVariable(
      NasaBlackwell theNasaBlackwellCalculator,
      List<Amount<Angle>> anglesOfAttack,
      Amount<Length> liftingSurfaceMAC,
      List<Amount<Length>> liftingSurfaceDimensionalY,
      List<Double> liftingSurfaceCl0Distribution, // all distributions must have the same length!!
      List<Double> liftingSurfaceCLAlphaDegDistribution,
      List<Double> liftingSurfaceCLforCMMatrix,
      List<List<Double>> liftingSurfaceCmACDistribution,
      List<Double> liftingSurfaceXACadimensionalDistribution,
      List<Amount<Length>> liftingSurfaceChordDistribution,
      List<Amount<Length>> liftingSurfaceXLEDistribution,
      List<List<Double>>
          airfoilClMatrix, // this is a list of list. each list is referred to an airfoil along the
      // semispan
      List<Amount<Angle>>
          anglesOfAttackClMatrix, // references angle of attack of the list of list airfoilClMatrix
      Amount<Area> liftingSurfaceArea,
      Amount<Length> momentumPole // referred to the origin of LRF
      ) {

    List<Double> liftingSurfaceMomentCoefficient = new ArrayList<>();

    double[] distancesArrayAC,
        clDistribution,
        alphaDistribution,
        clInducedDistributionAtAlphaNew,
        cmDistribution,
        cCm,
        xcPfracC;
    double cmActual;
    int numberOfAlphas = anglesOfAttack.size();
    int numberOfPointSemiSpanWise = liftingSurfaceCl0Distribution.size();

    for (int i = 0; i < numberOfAlphas; i++) {

      clDistribution = new double[numberOfPointSemiSpanWise];
      alphaDistribution = new double[numberOfPointSemiSpanWise];
      clInducedDistributionAtAlphaNew = new double[numberOfPointSemiSpanWise];
      distancesArrayAC = new double[numberOfPointSemiSpanWise];
      cmDistribution = new double[numberOfPointSemiSpanWise];
      cCm = new double[numberOfPointSemiSpanWise];
      xcPfracC = new double[numberOfPointSemiSpanWise];

      theNasaBlackwellCalculator.calculate(anglesOfAttack.get(i));
      clDistribution = theNasaBlackwellCalculator.getClTotalDistribution().toArray();
      //			clInducedDistributionAtAlphaNew = clDistribution;

      for (int ii = 0; ii < numberOfPointSemiSpanWise; ii++) {
        alphaDistribution[ii] =
            (clDistribution[ii] - liftingSurfaceCl0Distribution.get(ii))
                / liftingSurfaceCLAlphaDegDistribution.get(ii);

        if (alphaDistribution[ii] < anglesOfAttack.get(0).doubleValue(NonSI.DEGREE_ANGLE)) {
          clInducedDistributionAtAlphaNew[ii] =
              liftingSurfaceCLAlphaDegDistribution.get(ii) * alphaDistribution[ii]
                  + liftingSurfaceCl0Distribution.get(ii);
        } else {
          clInducedDistributionAtAlphaNew[ii] =
              MyMathUtils.getInterpolatedValue1DLinear(
                  MyArrayUtils.convertListOfAmountTodoubleArray(anglesOfAttackClMatrix),
                  MyArrayUtils.convertToDoublePrimitive(
                      MyArrayUtils.convertListOfDoubleToDoubleArray(airfoilClMatrix.get(ii))),
                  alphaDistribution[ii]);
        }

        cmActual =
            MyMathUtils.getInterpolatedValue1DLinear(
                MyArrayUtils.convertToDoublePrimitive(liftingSurfaceCLforCMMatrix),
                MyArrayUtils.convertToDoublePrimitive(liftingSurfaceCmACDistribution.get(ii)),
                clInducedDistributionAtAlphaNew[ii]);

        //				xcPfracC[ii] = liftingSurfaceXACadimensionalDistribution.get(ii) -
        //						(cmActual/
        //								clInducedDistributionAtAlphaNew[ii]);

        xcPfracC[ii] = 0.25 - (cmActual / clInducedDistributionAtAlphaNew[ii]);

        distancesArrayAC[ii] =
            momentumPole.doubleValue(SI.METER)
                - (liftingSurfaceXLEDistribution.get(ii).doubleValue(SI.METER)
                    + (xcPfracC[ii]
                        * liftingSurfaceChordDistribution.get(ii).doubleValue(SI.METER)));

        cmDistribution[ii] =
            clInducedDistributionAtAlphaNew[ii]
                * (distancesArrayAC[ii]
                    / liftingSurfaceChordDistribution.get(ii).doubleValue(SI.METER));

        cCm[ii] =
            cmDistribution[ii]
                * liftingSurfaceChordDistribution.get(ii).doubleValue(SI.METER)
                * liftingSurfaceChordDistribution.get(ii).doubleValue(SI.METER);
      }
      //			System.out.println(" distance " +  Arrays.toString(distancesArrayAC));
      //			System.out.println(" xcp " +  Arrays.toString(xcPfracC));
      //			System.out.println(" cl " +  Arrays.toString(clDistribution));
      //			System.out.println(" cl new " +  Arrays.toString(clInducedDistributionAtAlphaNew));
      //			System.out.println(" cm " + Arrays.toString(cmDistribution) );
      //			System.out.println(" ccm " + Arrays.toString(cCm));

      cCm[numberOfPointSemiSpanWise - 1] = 0;

      liftingSurfaceMomentCoefficient.add(
          i,
          ((2
                  / (liftingSurfaceArea.doubleValue(SI.SQUARE_METRE)
                      * liftingSurfaceMAC.doubleValue(SI.METER)))
              * MyMathUtils.integrate1DSimpsonSpline(
                  MyArrayUtils.convertListOfAmountTodoubleArray(liftingSurfaceDimensionalY), cCm)));
    }
    return liftingSurfaceMomentCoefficient;
  }