コード例 #1
0
def get_max_cl(Re, r):
    """
    Analyze airfoil at a fixed Re,
    changing aoa from 10 to 15 by 0.1
    and returns cl, cd, aoa that makes maximum cl
    """
    xf = XFoil()
    if r <= 0.175:
        xf.airfoil = naca6409
    else:
        xf.airfoil = naca2412
    xf.Re = Re
    xf.Re = Re
    xf.max_iter = 200
    xf.n_crit = 9.00
    xf.xtr = [1.00, 1.00]
    xf.M = 0
    a_seq, cl_seq, cd_seq, cm_seq, cp_seq = xf.aseq(10, 15, 0.1)
    # ignore nan by making it 0
    cl_seq = np.nan_to_num(cl_seq)
    # find the maximum cl
    cl_maxi = np.max(cl_seq)
    # index of the maximum cl
    idx = np.argmax(cl_seq)
    return round(cl_maxi, 2), round(a_seq[idx], 2), round(cd_seq[idx], 2)
コード例 #2
0
ファイル: server.py プロジェクト: gabachour44/achourfoil
def xfoil():
    x = request.args.get('x')
    y = request.args.get('y')
    Re = float(request.args.get('Re'))
    M = float(request.args.get('M'))
    Alpha = float(request.args.get('Alpha'))
    x = x.split()
    y = y.split()
    ctrlX = [float(ele) for ele in x]
    ctrlY = [float(ele) for ele in y]
    #bezierX, bezierY = airfoil(ctrlX, ctrlY, 16)

    xf = XFoil()
    xf.airfoil = Airfoil(np.array(ctrlX), np.array(ctrlY))
    xf.repanel()

    xf.Re = Re
    xf.M = 0
    xf.max_iter = 100

    aero = xf.a(Alpha)
    xcp, cp = xf.get_cp_distribution()
    y = savgol_filter(cp, 5, 2)
    for i in range(30):
        y = savgol_filter(y, 5, 2)
    LD = aero[0] / aero[1]
    vol = PolyArea(ctrlX, ctrlY)

    return jsonify(result=str(round(aero[0], 3)) + " " +
                   str(round(aero[1], 3)) + " " + str(round(aero[2], 3)) +
                   " " + str(round(LD, 2)) + " " + str(round(vol, 3)),
                   xcp=xcp.tolist(),
                   cp=y.tolist())
コード例 #3
0
def get_cls(coords):
  xf = XFoil()
  xf.print = False
  cl_s = []
  for coord in coords:
    cl = get_cl(coord, xf)
    cl_s.append(cl)
  
  return np.array(cl_s)
コード例 #4
0
ファイル: main_GUI.py プロジェクト: melonTai/foilOpt
    def evaluate(self, individual):
        ratios = self.decoder(individual, self.code_division)
        datlist_list = [fc.read_datfile(file) for file in self.datfiles]
        datlist_shaped_list = [
            fc.shape_dat(datlist) for datlist in datlist_list
        ]
        newdat = fc.interpolate_dat(datlist_shaped_list, ratios)

        foil_para = fc.get_foil_para(newdat)

        datx = np.array([ax[0] for ax in newdat])
        daty = np.array([ax[1] for ax in newdat])
        newfoil = Airfoil(x=datx, y=daty)

        mt, mta, mc, mca, s = foil_para

        penalty = 0
        for g, p in zip(self.gs, self.penalties):
            if (not g):
                penalty += p

        xf = XFoil()
        xf.airfoil = newfoil
        xf.Re = self.re
        xf.max_iter = 60

        print(self.assigns, self.datfiles)
        scope = locals()
        exec(self.assigns, scope)
        #----------------------------------
        #目的値
        #----------------------------------
        try:
            obj1, obj2, obj3 = [eval(o) for o in self.Os]
        except IndexError as e:
            obj1, obj2, obj3 = [1.0] * self.NOBJ
            traceback.print_exc()
        except SyntaxError as e:
            raise ValueError("invalid objection")

        if (np.isnan(obj1) or obj1 > 1):
            obj1 = 1
        if (np.isnan(obj2) or obj2 > 1):
            obj2 = 1
        if (np.isnan(obj3) or obj3 > 1):
            obj3 = 1

        obj1 += penalty
        obj2 += penalty
        obj3 += penalty

        return [obj1, obj2, obj3]
コード例 #5
0
    def initialize(self):
        super().initialize()
        self.options.declare("print", default=False, types=bool)

        xf = XFoil()
        xf.print = False
        self.options.declare("_xf", default=xf, types=XFoil, allow_none=True)
        self.options.declare("_pool",
                             default=ThreadPool(processes=1),
                             types=ThreadPool,
                             allow_none=True)

        self.recording_options["options_excludes"] = ["_xf", "_pool"]
コード例 #6
0
def get_torque(angular_velocity):
    torque_sum_small = 0
    torque_sum_large = 0
    w = angular_velocity
    for key, value in dfdict.items():
        value["blade_velocity"] = value['r_position'] * w
        value["relative_velocity"] = round(
            math.sqrt(value["blade_velocity"]**2 + value["wind_velocity"]**2),
            2)
        value["arctan"] = math.degrees(
            math.atan2(value["wind_velocity"], value["blade_velocity"]))
        aoa = round(value["arctan"] - value["pitch_angle"], 2)
        value["angle_of_attack"] = aoa
        re_n = round(
            value["relative_velocity"] * value["chord_length"] / 0.00001511, 3)
        value["Reynolds_number"] = re_n
        xf = XFoil()
        if key < 13:
            xf.airfoil = naca6409
        else:
            xf.airfoil = naca2412
        xf.Re = re_n
        xf.max_iter = 100
        xf.n_crit = 9.00
        xf.xtr = [1.00, 1.00]
        xf.M = 0
        value["Cl"], value["Cd"], value["Cm"], value["Cp"] = xf.a(aoa)
        force_reference = 0.5 * density * value["relative_velocity"]**2
        if math.isnan(value["Cl"]):
            value["torque"] = 0
        else:
            lift = value["Cl"] * force_reference * 0.0125 * value[
                'chord_length']
            drag = value["Cd"] * force_reference * 0.0125 * value[
                'chord_length']
            value["torque"] = value["r_position"] * (
                lift * math.sin(math.radians(value["pitch_angle"])) -
                drag * math.cos(math.radians(value["pitch_angle"])))
        if key < 13:
            torque_sum_small += value["torque"]
        else:
            pass
        if key > 0:
            torque_sum_large += value["torque"]
        else:
            pass
    df2 = pd.DataFrame.from_dict(dfdict, orient="index")
    df_collection.append(df2)
    torque_sum_avg = 0.5 * (torque_sum_small + torque_sum_large)
    return torque_sum_avg
    def __init__(self):
        self.xf = XFoil()
        self.min_action = np.array([0.1, 0.05, 1.0, 0.05, 0.4, 1.0, 0.0])
        self.max_action = np.array([0.4, 0.4, 3.0, 3.0, 8.0, 10.0, 10.0])
        ''' 測試開始, 可省略測試'''
        #        (.01, .4), (.05, .4), (1, 3), (0.05, 3), (0.4, 8), (1, 10)

        #        self.xf.airfoil = naca0012
        #        k = [0.08813299, 0.28250898, 2.80168427, 2.56204214, 1.48703742, 8.53824561]
        #        k = [0.34422, 0.38976, 1.1, 2.9989, 1.6071, 9.9649]
        k = [0.1584, 0.1565, 2.1241, 1.8255, 11.6983, 3.827]  # org
        #        k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009]
        #        k = [0.1472, 0.1638, 2.1041, 1.8156, 3.8141, 11.6808]
        #        k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009]
        #        k = [0.1783,  0.1366,  2.1283,  1.8073,  3.8325, 11.7176]
        #        k = [0.25840,  0.14474,  2.22410,  1.92550, 11.59984,  3.92623]
        airfoil = construct_airfoil(*k)
        x, y = get_coords_plain(airfoil._spline(100))
        self.xf.airfoil = Airfoil(x=x, y=y)
        #        test_airfoil = NACA4(2, 3, 15)
        #        a = test_airfoil.max_thickness()
        #        self.xf.airfoil = test_airfoil.get_coords()
        self.xf.Re = 1e6
        self.xf.M = 0.04
        self.xf.print = False
        cl, cd, cm, cp = self.xf.a(9)
        x = np.array(x, dtype='float32')
        y = np.array(y, dtype='float32')
        reward = cl / cd
        #        reward = cl
        ''' 測試結束, 可省略測試'''

        #        cl, cd, cm, cp = self.xf.a(12.2357)
        #        self.action_space = spaces.Discrete(30)
        self.action_space = spaces.Box(self.min_action,
                                       self.max_action,
                                       dtype=np.float32)

        #        high = np.array([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0])
        high = np.array([
            100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0,
            100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0,
            100.0, 100.0, 100.0, 100.0
        ])
        self.observation_space = spaces.Box(
            -high, high, dtype=np.float32)  #創建state大小(25,f22機翼,b3cl.cd.aoa)
        self.seed()
        self.viewer = None
        self.state = None
        self.steps_beyond_done = None
コード例 #8
0
def cl_visc_analysis(airfoil, cl_i, cl_f, cl_step, re, mach, max_iter, id):
    """Viscous analysis over range of lift coefficients."""
    # Initializes airfoil and assigns NACA
    xf = XFoil()
    xf.naca(airfoil)
    xf.max_iter = max_iter
    xf.Re = re
    xf.M = mach
    # Collects values
    a, cl, cd, cm, cp = xf.cseq(cl_i, cl_f, cl_step)
    x, cp_0 = xf.get_cp_distribution()
    # Plots all the data
    plot(a, cl, cd, cm, cp, x, cp_0, id)
コード例 #9
0
def alpha_visc_analysis(airfoil, alpha_i, alpha_f, alpha_step, re, mach,
                        max_iter, id):
    """Viscous analysis over range of angle of attacks."""
    # Initializes airfoil and assigns NACA
    xf = XFoil()
    xf.naca(airfoil)
    xf.max_iter = max_iter
    xf.Re = re
    xf.M = mach
    # Collects values
    a, cl, cd, cm, cp = xf.aseq(alpha_i, alpha_f, alpha_step)
    x, cp_0 = xf.get_cp_distribution()
    # Plots all the data
    plot(a, cl, cd, cm, cp, x, cp_0, id)
コード例 #10
0
def cl_inv_analysis(airfoil, cl_i, cl_f, cl_step, max_iter, id):
    """Inviscid analysis over range of angle of attacks."""
    # Initializes airfoil and assigns NACA
    xf = XFoil()
    xf.naca(airfoil)
    xf.max_iter = max_iter
    # Collects values
    a, cl, cd, cm, cp = xf.cseq(cl_i, cl_f, cl_step)
    x, cp_0 = xf.get_cp_distribution()
    # Plots all the data
    plot(a, cl, cd, cm, cp, x, cp_0, id)
コード例 #11
0
def get_cl(coord, xf=None, angle=5):
  if xf is None:
    xf = XFoil()
    xf.print = False

  xf.Re = 3e6
  xf.max_iter = 100
  datax, datay = coord.reshape(2, -1)
  xf.airfoil = Airfoil(x=datax, y=datay)
  c = xf.a(angle)
  cl= c[0]
  return cl
コード例 #12
0
def getCoefficients(naca,
                    reynolds=1e6,
                    iterations=20,
                    angle=10,
                    angle_step=.5):
    xf = XFoil()
    xf.naca(f"{naca:04d}")
    xf.Re = reynolds
    xf.max_iter = 20
    a, cl, cd, cm, cp = xf.aseq(0, angle, .5)
    ratio = cl / cd
    max_idx = np.nanargmax(ratio)
    return (ratio[max_idx], a[max_idx]), a, cl, cd, max_idx
コード例 #13
0
ファイル: nsga3_spline.py プロジェクト: melonTai/foilOpt
    def evaluate(self,individual):
        DELTA = 1e10
        #----------------------------------
        #遺伝子に基づいて新翼型を生成
        #----------------------------------
        #遺伝子に基づきスプライン翼型を作成
        x = individual[:int(len(individual)/2)]
        x.insert(0,1.0)
        x.insert(int(len(x)/2)+1,0.0)
        x.append(1.0)
        y = individual[int(len(individual)/2):]
        if not (all([u - d > 0 for u, d in zip(y[:int(len(y)/2)], y[int(len(y)/2):])]) or all([u - d < 0 for u, d in zip(y[:int(len(y)/2)], y[int(len(y)/2):])])):
            print("crossed")
            return [DELTA*10]*self.NOBJ
        y.insert(0,0.0)
        y.insert(int(len(y)/2)+1,0.0)
        y.append(0.0)
        newdat = fc.spline_foil(x, y, 200)
        shape_dat = fc.shape_dat([[a, b] for a, b in zip(newdat[0][::-1], newdat[1][::-1])])

        #翼型の形に関する情報を取得する
        foil_para = fc.get_foil_para(shape_dat)
        mt, mta, mc, mca, s, crossed, bd, bt, bc, smooth, td = foil_para
        # mt: 最大翼厚(百分率)
        # mta: 最大翼厚位置(百分率)
        # mc: 最大キャンバー(百分率)
        # mca: 最大きゃんばー位置(百分率)
        # s: 翼型の下面における、最大y座標-最小y座標
        # crossed: 翼型が交差しているならTrue,それ以外ならFalse
        # bd: 翼型の粗さ(大きいほど粗い)
        # bt: 翼厚分布の粗さ(大きいほど粗い)
        # bc: キャンバー分布の粗さ(大きいほど粗い)
        # smooth: 無視
        # td: 翼厚分布

        if crossed:
            print("crossed_a")
            return [DELTA*10]*self.NOBJ
        else:
            print("hi_a")

        #新しい翼型をAerofoilオブジェクトに適用
        datx = np.array(newdat[0][::-1])
        daty = np.array(newdat[1][::-1])
        newfoil = Airfoil(x = datx, y = daty)

        #翼型の形に関する拘束条件
        penalty = 0
        if not all([t >= 0.0035 for t in td[10:80]]):
            penalty += 100 * (sum([abs(t - 0.0035)*10 for t in td[15:85] if t - 0.0035 < 0]))
        if not all([t <= 0.015 for t in td[:15]]):
            penalty += 100 * (sum([abs(t - 0.015)*10 for t in td[:15] if t > 0.015]))
        if mta > 0.4:
            penalty += 100 * (mta - 0.4)
        if mc < 0.0:
            penalty += 100 * (-mc)
        if datx[0] > 1.002 or datx[0] < 0.998:
            print("invalid foil")
            return [DELTA*10]*self.NOBJ
        #----------------------------------
        #新翼型の解析
        #----------------------------------
        try:
            xf = XFoil()
            #レイノルズ数の設定
            xf.airfoil = newfoil
            xf.Re = self.re
            xf.print = False
            xf.max_iter = 40

            #xf.polar = "polar" + id
            #境界要素法計算時1ステップにおける計算回数
            #xf.repanel(n_nodes = 180)
            #計算結果格納
            #result = xf.OneAlpha()
            cl, cd, cm, cp  = xf.a(5.0)
        #----------------------------------
        #目的値
        #----------------------------------
            if cl >= 0:
                obj1 = 1/cl
            else:
                obj1 = self.delta
            
            obj2 = cd


        except Exception as e:
            obj1,obj2=[DELTA]*self.NOBJ
            traceback.print_exc()

        if (np.isnan(obj1)):
            obj1 = DELTA
        if (np.isnan(obj2)):
            obj2 = DELTA

        return [obj1 + penalty, obj2 + penalty]
コード例 #14
0
        a_p_a = a_p

v_r = math.sqrt(v_1 ** 2 * (1 - a_max) ** 2 + prop_omega ** 2 * r ** 2 * (a_p_max - 1) ** 2)

# ITERATION & CALL TO XFOIL
c_l = cl_i

if

    c = (a_max * 8 * pi * r * math.sin(phi) ** 2) / ((1 - a_max) * prop_blades * c_l * math.cos(phi))
    re = (v_r * c) / (nu_mars)

    # XFOIL #######

    from xfoil import XFoil
    xf = XFoil()

    # Import an airfoil
    from xfoil.test import XXXXX
    xf.airfoil = XXXXX

    # Setting up the analysis parameters
    xf.Re = re
    xf.max_iter = 100
    xf.M = 0.7

    # Obtaining the angle of attack, lift coefficient, drag coefficient and momentum coefficient of the airfoil
    a, cl, cd, cm = xf.aseq(0, 30, 0.5)


コード例 #15
0
def analyze_airfoil(x,
                    y_u,
                    y_l,
                    cl,
                    rey,
                    mach=0,
                    xf=None,
                    pool=None,
                    show_output=False):
    """
    Analyze an airfoil at a given lift coefficient for given Reynolds and Mach numbers using XFoil.

    Parameters
    ----------
    x : array_like
        Airfoil x-coordinates
    y_u, y_l : array_like
        Airfoil upper and lower curve y-coordinates
    cl : float
        Target lift coefficient
    rey, mach : float
        Reynolds and Mach numbers
    xf : XFoil, optional
        An instance of the XFoil class to use to perform the analysis. Will be created if not given
    pool : multiprocessing.ThreadPool, optional
        An instance of the multiprocessing.Threadpool class used to run the xfoil_worker. Will be created if not given
    show_output : bool, optional
        If True, a debug string will be printed after analyses. False by default.

    Returns
    -------
    cd, cm : float or np.nan
        Drag and moment coefficients of the airfoil at specified conditions, or nan if XFoil did not run successfully
    """
    # If the lower and upper curves swap, this is a bad, self-intersecting airfoil. Return 1e27 immediately.
    if np.any(y_l > y_u):
        return np.nan
    else:
        clean_xf = False
        if xf is None:
            xf = XFoil()
            xf.print = show_output
            clean_xf = True

        clean_pool = False
        if pool is None:
            pool = ThreadPool(processes=1)
            clean_pool = True

        xf.airfoil = Airfoil(x=np.concatenate((x[-1:0:-1], x)),
                             y=np.concatenate((y_u[-1:0:-1], y_l)))
        xf.Re = rey
        xf.M = mach
        xf.max_iter = 100
        xf.n_crit = 0.1
        cd, cm = pool.apply(xfoil_worker, args=(xf, cl))

    if clean_xf:
        del xf
    if clean_pool:
        del pool

    return cd, cm, None if clean_xf else xf
コード例 #16
0
        ax.yaxis.set_minor_locator(ticker.MultipleLocator(mult_y / 5 * Y_0))
    if (grd == True):
        ax.grid(b=True, which='major', axis='both')
    else:
        ax.grid(b=False, which='major', axis='both')
    if (minorgrd == True):
        ax.grid(b=True, which='minor', axis='both')
    else:
        ax.grid(b=False, which='minor', axis='both')

    if (x_lim != None):
        ax.set_xlim(x_lim)
    if (y_lim != None):
        ax.set_ylim(y_lim)
    return ax


"""#########################################################################"""

from xfoil.test import naca0012
from xfoil import XFoil

xf = XFoil()
xf.airfoil = naca0012
xf.Re = 1e5
xf.max_iter = 20
a, cl, cd, cm, co = xf.aseq(-20, 20, 1)

fig, axarr = plt.subplots(1, 1, figsize=(6, 4))
axarr.plot(a, cl)
plt.show()
コード例 #17
0
#!/usr/bin/python3
from xfoil import XFoil
import matplotlib.pyplot as plt
xf = XFoil()

xf.load("revclarky.dat")
xf.Re = 1e5
xf.M = 0
xf.max_iter = 100
a, cl, cd, cm, cp = xf.aseq(-2, 2, 0.5)
plt.plot(a, cl)
plt.title("alfa vs cl")
plt.show()

#plt.plot(xf.airfoil.x,xf.airfoil.y)
#plt.axis('equal')
#plt.show()
コード例 #18
0
def saveResults():
    drag = Aerofoils_obj.cd * 0.5 * rho * (velocity**2) * mac * span
    datarow = [span, chord, drag]
    with open(r'viscous_drag_landscape_results.csv', 'a', newline='') as f:
        writer = csv.writer(f)
        writer.writerow(datarow)


rho = 1.1685
velocity = 41.6667
g = 9.81
reynolds_div_chord = 2794120

mass = 100

xf = XFoil()
xf.max_iter = 100

print("Max iterations: {0}\nMass: {1}Kg".format(xf.max_iter, mass))

START_CHORD = 0.1
END_CHORD = 0.3
CHORD_POINTS_PER_METRE = 100

START_SPAN = 8
END_SPAN = 10
SPAN_POINTS_PER_METRE = 10

chord_points = int((END_CHORD - START_CHORD) * CHORD_POINTS_PER_METRE)
chord_increment = float((END_CHORD - START_CHORD) / chord_points)
コード例 #19
0
from xfoil import XFoil
import matplotlib.pyplot as plt

xf = XFoil()

xf.load("clarky.dat")
plt.plot(xf.airfoil.x, xf.airfoil.y)
plt.axis('equal')
plt.show()
コード例 #20
0
aoa_h = 34

fig, ax = plt.subplots(1, 1, figsize=(9, 8))

klist = [1]

for k in range(1):
    print(k)
    x = aifoils[k]['x'].values
    y = aifoils[k]['y'].values

    ang_low = -32
    ang_high = 32
    ang_spacing = 2

    xfc = XFoil()
    xfc.airfoil = Airfoil(x, y)
    xfc.Re = re[k]
    xfc.max_iter = 40
    ac, clc, cdc, cmc, cpminc = xfc.aseq(ang_low, ang_high, ang_spacing)

    df = aifoils_cfd[k].where(aifoils_cfd[k]['alpha [deg]'] >= aoa_l)
    df = df.where(aifoils_cfd[k] <= aoa_h)
    df = df.dropna()  #.values

    cl_panel = []
    cdp_panel = []

    for aoa in df['alpha [deg]']:
        data_xy = aifoils[k].values
        CL, CDP, Cp, pp = panel(data_xy[:, :], alfader=aoa)
コード例 #21
0

#1. Define Aero and Structural grid
Nel_struct = 6  # Number of elements per surface in struct grid
Nel_aero = 30  # Number of elements per surface in aero grid

Xwing_aero = Aero.NACA4(1.0, 0.12, 0.03, 0.4,
                        Nel_aero)  #create aero grid nodes
Xwing_struct = Aero.NACA4(1.0, 0.12, 0.03, 0.4,
                          Nel_struct)  #create aero grid nodes

Xwing_aero1 = Aero.NACA4(1.0, 0.13, 0.03, 0.3,
                         Nel_aero)  #create aero grid nodes
Xwing_struct1 = Aero.NACA4(1.0, 0.13, 0.03, 0.3,
                           Nel_struct)  #create aero grid nodes
xf = XFoil()
aa = Xwing_aero1[:, 0]
b = Xwing_aero1[:, 1]
archive3 = open('lt.txt', 'w')

for line in range(len(aa)):
    aux = [aa[line], b[line]]
    string = str(aux).replace("[",
                              " ").replace(",",
                                           " ").replace("]",
                                                        " ").replace("'", " ")
    archive3.writelines(string + '\n')
    aux.clear

# Calculates the aerodynamic coeff using Xfoil
archive3.close()
コード例 #22
0
ファイル: main_mixfoil.py プロジェクト: melonTai/foilOpt
def evaluate(individual):
    global code_division

    #----------------------------------
    #遺伝子にも続いて新翼型を生成
    #----------------------------------
    #遺伝子をデコード
    ratios = decoder(individual, code_division)

    #遺伝子に基づき翼型を混合して、新しい翼型を作る
    datlist_list = [fc.read_datfile(file) for file in datfiles]
    datlist_shaped_list = [fc.shape_dat(datlist) for datlist in datlist_list]
    newdat = fc.interpolate_dat(datlist_shaped_list,ratios)

    #翼型の形に関する情報を取得する
    #foilpara == [最大翼厚、最大翼厚位置、最大キャンバ、最大キャンバ位置、S字の強さ]
    foil_para = fc.get_foil_para(newdat)

    #新しい翼型をAerofoilオブジェクトに適用
    datx = np.array([ax[0] for ax in newdat])
    daty = np.array([ax[1] for ax in newdat])
    newfoil = Airfoil(x = datx, y = daty)

    mt, mta, mc, mca, s = foil_para

    #----------------------------------
    #翼の形に関する拘束条件
    #----------------------------------
    penalty = 0
    print('===================')
    if(mc<0):
        print("out of the border")
        print("reverse_cmaber")
        penalty -= mc
    if(mt<0.08):
        print("out of the border")
        print("too_thin")
        penalty += 0.08-mt
    if(mt>0.11):
        print("out of the border")
        print("too_fat")
        penalty += mt-0.11
    #if(foil_para[4]>0.03):
    #    print("out of the border")
    #    print("peacock")
    #    print('===================')
    #    return (1.0+(foil_para[4]-0.03),)*NOBJ
    if(mta<0.23):
        print("out of the border")
        print("Atama Dekkachi!")
        penalty += 0.23 - mta
    if(mta>0.3):
        print("out of the border")
        print("Oshiri Dekkachi!")
        penalty += mta - 0.3

    #----------------------------------
    #新翼型の解析
    #----------------------------------
    xf = XFoil()
    xf.airfoil = newfoil
    #レイノルズ数の設定
    xf.Re = 1.5e5
    #境界要素法計算時1ステップにおける計算回数
    xf.max_iter = 60
    #座標整形
    xf.repanel(n_nodes = 300)
    xf.print = False
    #計算結果格納
    a, cl, cd, cm, cp = xf.cseq(0.4, 1.1, 0.1)
    lr = [l/d for l, d in zip(cl,cd)]
    #----------------------------------
    #目的値
    #----------------------------------
    try:
        #揚抗比の逆数を最小化
        obj1 = 1/lr[1]
        #揚抗比のピークを滑らかに(安定性の最大化)
        maxlr = max(lr)
        maxlr_index = lr.index(maxlr)
        obj2 = abs(maxlr - lr[maxlr_index+1])

        #下面の反りを最小化(製作再現性の最大化)
        obj3 = foil_para[4]
    except Exception as e:
        obj1,obj2,obj3=[1.0]*NOBJ
        traceback.print_exc()

    if (np.isnan(obj1) or obj1 > 1):
        obj1 = 1
    if (np.isnan(obj2) or obj2 > 1):
        obj2 = 1
    if (np.isnan(obj3) or obj3 > 1):
        obj3 = 1

    obj1 += penalty
    obj2 += penalty
    obj3 += penalty

    print("individual",individual)
    print("evaluate",obj1,obj2,obj3)
    print("max_thickness",foil_para[0])
    print("at",foil_para[1])
    print("max_camber",foil_para[2])
    print("at",foil_para[3])
    print("S",foil_para[4])
    print('===================')

    return [obj1, obj2, obj3]
コード例 #23
0
ファイル: nsga3_mixfoil.py プロジェクト: melonTai/foilOpt
    def evaluate(self, individual):
        #解析が発散した際の評価値
        DELTA = 1e10
        #----------------------------------
        #遺伝子に基づいて新翼型を生成
        #----------------------------------
        #遺伝子をデコード
        ratios = self.decoder(individual, self.code_division)

        #遺伝子に基づき翼型を混合して、新しい翼型を作る
        datlist_list = [fc.read_datfile(file) for file in self.datfiles]
        datlist_shaped_list = [
            fc.shape_dat(datlist) for datlist in datlist_list
        ]
        newdat = fc.interpolate_dat(datlist_shaped_list, ratios)

        #翼型の形に関する情報を取得する
        mt, mta, mc, mca, s, crossed, bd, bt, bc, smooth, td = fc.get_foil_para(
            newdat)

        #新しい翼型をAerofoilオブジェクトに適用
        datx = np.array([ax[0] for ax in newdat])
        daty = np.array([ax[1] for ax in newdat])
        newfoil = Airfoil(x=datx, y=daty)

        #----------------------------------
        #翼の形に関する拘束条件
        #----------------------------------
        penalty = 0
        #キャンバに関する拘束条件
        if (mc < 0):
            penalty -= mc
        #最大翼厚に関する拘束条件
        if (mt < 0.08):
            penalty += 0.08 - mt
        if (mt > 0.11):
            penalty += mt - 0.11
        #最大翼厚位置に関する拘束条件
        if (mta < 0.23):
            penalty += 0.23 - mta
        if (mta > 0.3):
            penalty += mta - 0.3

        #----------------------------------
        #新翼型の解析
        #----------------------------------
        xf = XFoil()
        xf.airfoil = newfoil
        #レイノルズ数の設定
        xf.Re = self.re
        #境界要素法計算時1ステップにおける計算回数
        xf.max_iter = 60
        xf.print = False

        #計算結果格納
        a, cl, cd, cm, cp = xf.cseq(0.4, 1.1, 0.1)
        #----------------------------------
        #目的値
        #----------------------------------
        try:
            #揚抗比の逆数を最小化
            obj1 = 1 / lr[1]

            #揚抗比のピークを滑らかに(安定性の最大化)
            maxlr = max(lr)
            maxlr_index = lr.index(maxlr)
            obj2 = abs(maxlr - lr[maxlr_index + 1])

            #下面の反りを最小化(製作再現性の最大化)
            obj3 = s

        except Exception as e:
            obj1, obj2, obj3 = [DELTA] * self.NOBJ
            traceback.print_exc()

        if (np.isnan(obj1) or obj1 > 1):
            obj1 = DELTA
        if (np.isnan(obj2) or obj2 > 1):
            obj2 = DELTA
        if (np.isnan(obj3) or obj3 > 1):
            obj3 = DELTA

        obj1 += penalty
        obj2 += penalty
        obj3 += penalty

        return [obj1, obj2, obj3]
コード例 #24
0
def feature_xfoil(cst_u,
                  cst_l,
                  t,
                  Minf: float,
                  Re,
                  AoA,
                  n_crit=0.1,
                  fname='feature-xfoil.txt'):
    '''
    Evaluate by xfoil and extract features.

    Inputs:
    ---
    cst-u, cst-l:   list of upper/lower CST coefficients of the airfoil. \n
    t:      airfoil thickness or None \n
    Minf:   free stream Mach number for wall Mach number calculation \n
    Re, AoA (deg): flight condition (s), float or list, for Xfoil \n
    n_crit: critical amplification ratio for transition in xfoil \n
    fname:  output file name. If None, then no output \n

    ### Dependencies: cst-modeling3d, xfoil  
    '''

    from cst_modeling.foil import cst_foil
    from xfoil import XFoil
    from xfoil.model import Airfoil

    #TODO: Build foil
    #! 201 is the maximum amount of points that xfoil can handle
    #! tail = 0.001 is to avoid point overlap
    xx, yu, yl, t0, R0 = cst_foil(201, cst_u, cst_l, x=None, t=t, tail=0.001)

    #! xfoil do not support leading edge of (0,0) on both upper and lower surface
    x = np.array(list(reversed(xx[1:])) + xx[1:])
    y = np.array(list(reversed(yu[1:])) + yl[1:])
    foil = Airfoil(x, y)

    #TODO: Xfoil
    xf = XFoil()
    xf.print = False
    xf.airfoil = foil
    xf.max_iter = 40

    #* Transition by power law
    xf.n_crit = n_crit

    #TODO: Xfoil calculation
    if not isinstance(Re, list):
        Re = [Re]
        AoA = [AoA]

    n = len(Re)
    for i in range(n):

        xf.reset_bls()

        if Re[i] is not None:
            xf.Re = Re[i]

        cl, cd, cm, cp = xf.a(AoA[i])
        x, cp = xf.get_cp_distribution()

        print(xf.Re, AoA[i], cl)

        #* Extract features
        fF = PhysicalXfoil(Minf, AoA[i], Re[i])
        fF.setdata(x, y, cp)
        fF.extract_features()

        #* Output
        if fname is None:
            continue

        if i == 0:
            f = open(fname, 'w')
        else:
            f = open(fname, 'a')

        f.write('\n')
        f.write('%10s   %15.6f \n' % ('Minf', Minf))
        f.write('%10s   %15.6f \n' % ('AoA', AoA[i]))
        f.write('%10s   %15.6f \n' % ('Re', Re[i] / 1e6))
        f.write('%10s   %15.6f \n' % ('CL', cl))
        f.write('%10s   %15.6f \n' % ('Cd', cd))
        f.write('%10s   %15.6f \n' % ('Cm', cm))
        f.close()

        fF.output_features(fname=fname, append=True)
コード例 #25
0
from xfoil import XFoil
from xfoil.test import naca0012

xf = XFoil()
xf.airfoil = naca0012
xf.Re = 1e6
xf.max_iter = 40
a, cl, cd, cm, co = xf.aseq(-20, 20, 0.5)
コード例 #26
0
def total_dict(angular_velocity):
    torque_sum = 0
    w = angular_velocity
    for key, value in dfdict.items():
        value["blade_velocity"] = value['r_position'] * w
        value["relative_velocity"] = round(
            math.sqrt(value["blade_velocity"]**2 + value["wind_velocity"]**2),
            2)
        value["arctan"] = math.degrees(
            math.atan2(value["wind_velocity"], value["blade_velocity"]))
        aoa = round(value["arctan"] - value["pitch_angle"], 1)
        value["angle_of_attack"] = aoa
        re_n = round(value["relative_velocity"] * value["chord_length"] /
                     0.00001511)
        value["Reynolds_number"] = re_n
        xf = XFoil()
        if key < 13:
            xf.airfoil = naca6409
        else:
            xf.airfoil = naca2412
        xf.Re = round(re_n / 100) * 100
        xf.max_iter = 200
        xf.n_crit = 9.00
        xf.xtr = [1.00, 1.00]
        xf.M = 0
        c_l, c_d, c_m, c_p = xf.a(aoa)
        force_reference = 0.5 * density * value["relative_velocity"]**2
        if math.isnan(c_l):
            pass
        else:
            value["Cl"] = c_l
            value["Cd"] = c_d
            value["Cm"] = c_m
            value["Cp"] = c_p
            lift = c_l * force_reference * 0.0125 * value['chord_length']
            drag = c_d * force_reference * 0.0125 * value['chord_length']
            value["lift"] = lift
            value["drag"] = drag
            # value["torque"] = value["r_position"] * lift * math.sin(math.radians(value["pitch_angle"]))
            torque = value["r_position"] * (
                lift * math.sin(math.radians(value["pitch_angle"])) -
                drag * math.cos(math.radians(value["pitch_angle"])))
            value["torque"] = torque
            torque_sum += torque
        xf.reset_bls()
    # detailed_df = pd.DataFrame.from_dict(dfdict, orient="index")
    # print(detailed_df)
    print(torque_sum, angular_velocity)
    return dfdict, torque_sum
コード例 #27
0
    def evaluate(self,individual):

        #----------------------------------
        #遺伝子に基づいて新翼型を生成
        #----------------------------------
        #遺伝子をデコード
        ratios = self.decoder(individual, self.code_division)

        #遺伝子に基づき翼型を混合して、新しい翼型を作る
        datlist_list = [fc.read_datfile(file) for file in self.datfiles]
        datlist_shaped_list = [fc.shape_dat(datlist) for datlist in datlist_list]
        newdat = fc.interpolate_dat(datlist_shaped_list,ratios)

        #翼型の形に関する情報を取得する
        #foilpara == [最大翼厚、最大翼厚位置、最大キャンバ、最大キャンバ位置、S字の強さ]
        foil_para = fc.get_foil_para(newdat)

        #新しい翼型をAerofoilオブジェクトに適用
        datx = np.array([ax[0] for ax in newdat])
        daty = np.array([ax[1] for ax in newdat])
        newfoil = Airfoil(x = datx, y = daty)

        mt, mta, mc, mca, s = foil_para

        #----------------------------------
        #翼の形に関する拘束条件
        #----------------------------------
        """
        penalty = 0
        for g, p in zip(self.gs, self.penalties):
            if(not g):
                penalty += p
        """

        penalty = 0
        print('===================')
        if(mc<0):
            print("out of the border")
            print("reverse_cmaber")
            penalty -= mc
        if(mt<0.08):
            print("out of the border")
            print("too_thin")
            penalty += 0.08-mt
        if(mt>0.11):
            print("out of the border")
            print("too_fat")
            penalty += mt-0.11
        #if(foil_para[4]>0.03):
        #    print("out of the border")
        #    print("peacock")
        #    print('===================')
        #    return (1.0+(foil_para[4]-0.03),)*NOBJ
        if(mta<0.23):
            print("out of the border")
            print("Atama Dekkachi!")
            penalty += 0.23 - mta
        if(mta>0.3):
            print("out of the border")
            print("Oshiri Dekkachi!")
            penalty += mta - 0.3

        #----------------------------------
        #新翼型の解析
        #----------------------------------
        xf = XFoil()
        xf.airfoil = newfoil
        #レイノルズ数の設定
        xf.Re = self.re
        #境界要素法計算時1ステップにおける計算回数
        xf.max_iter = 60
        #print("hi")
        #print(vars)
        #scope = locals()
        #var0, var1, var2, var3, var4, var5, var6, var7 = [0 if var == None or var == '' else eval(var,scope) for var in self.vars]

        #計算結果格納
        a, cl, cd, cm, cp = xf.cseq(0.4, 1.1, 0.1)
        lr = [l/d for l, d in zip(cl,cd)]
        #----------------------------------
        #目的値
        #----------------------------------
        """
        try:
            obj1,obj2,obj3 = [eval(o) for o in Os]
        except Exception as e:
            obj1,obj2,obj3=[1.0]*self.NOBJ
            traceback.print_exc()
        """

        try:
            #揚抗比の逆数を最小化
            obj1 = 1/lr[1]
            #揚抗比のピークを滑らかに(安定性の最大化)
            maxlr = max(lr)
            maxlr_index = lr.index(maxlr)
            obj2 = abs(maxlr - lr[maxlr_index+1])

            #下面の反りを最小化(製作再現性の最大化)
            obj3 = s
        except Exception as e:
            obj1,obj2,obj3=[1.0]*self.NOBJ
            traceback.print_exc()

        if (np.isnan(obj1) or obj1 > 1):
            obj1 = 1
        if (np.isnan(obj2) or obj2 > 1):
            obj2 = 1
        if (np.isnan(obj3) or obj3 > 1):
            obj3 = 1

        obj1 += penalty
        obj2 += penalty
        obj3 += penalty

        return [obj1, obj2, obj3]
コード例 #28
0
  if not use_dataset:
    npz = np.load(input_path)
    labels = npz[npz.files[0]]
    coords = npz[npz.files[1]]
  else:
    perfs_npz = np.load("./dataset/standardized_perfs.npz")
    coords_npz = np.load("./dataset/standardized_coords.npz")
    coords = coords_npz[coords_npz.files[0]]
    coord_mean = coords_npz[coords_npz.files[1]]
    coord_std = coords_npz[coords_npz.files[2]]
    perfs = perfs_npz[perfs_npz.files[0]]
    perf_mean = perfs_npz[perfs_npz.files[1]]
    perf_std = perfs_npz[perfs_npz.files[2]]

  xf = XFoil()
  xf.print = False
  cnt = 0
  print("start calculating!")
  start = time.time()
  coords = coords*coord_std+coord_mean if use_dataset else coords
  for label, coord in zip(labels, coords):
    cl = get_cl(xf, coord)
    if not np.isnan(cl):
      cnt+=1
      if type(label) is np.float64:
        label = str(round(label, 3))
      else:
        label = str(round(label[0],3))
      print("label: {0}, cl: {1}".format(label, cl))
コード例 #29
0
class XFoilEnv(gym.Env):
    """
    Description:
        A pole is attached by an un-actuated joint to a cart, which moves along a frictionless track. The pendulum starts upright, and the goal is to prevent it from falling over by increasing and reducing the cart's velocity.

    Source:
        This environment corresponds to the version of the cart-pole problem described by Barto, Sutton, and Anderson

    Observation: 
        Type: Box(4)
        Num	Observation                 Min         Max
        0	Cart Position             -4.8            4.8
        1	Cart Velocity             -Inf            Inf
        2	Pole Angle                 -24 deg        24 deg
        3	Pole Velocity At Tip      -Inf            Inf
        
    Actions:
        Type: Discrete(2)
        Num	Action
        0	Push cart to the left
        1	Push cart to the right
        
        Note: The amount the velocity that is reduced or increased is not fixed; it depends on the angle the pole is pointing. This is because the center of gravity of the pole increases the amount of energy needed to move the cart underneath it

    Reward:
        Reward is 1 for every step taken, including the termination step

    Starting State:
        All observations are assigned a uniform random value in [-0.05..0.05]

    Episode Termination:
        Pole Angle is more than 12 degrees
        Cart Position is more than 2.4 (center of the cart reaches the edge of the display)
        Episode length is greater than 200
        Solved Requirements
        Considered solved when the average reward is greater than or equal to 195.0 over 100 consecutive trials.
    """
    
    metadata = {
        'render.modes': ['human', 'rgb_array'],
        'video.frames_per_second' : 50
    }

    def __init__(self):
        self.xf = XFoil()
        self.min_action = np.array([0.1, 0.05, 1.0, 0.05, 0.4,  1.0,  0.0])
        self.max_action = np.array([0.4,  0.4, 3.0,  3.0, 8.0, 10.0, 10.0])
        ''' 測試開始, 可省略測試'''
#        (.01, .4), (.05, .4), (1, 3), (0.05, 3), (0.4, 8), (1, 10)

        #        self.xf.airfoil = naca0012
#        k = [0.08813299, 0.28250898, 2.80168427, 2.56204214, 1.48703742, 8.53824561]
#        k = [0.34422, 0.38976, 1.1, 2.9989, 1.6071, 9.9649]
        k = [0.1584, 0.1565, 2.1241, 1.8255, 11.6983, 3.827]  # org
#        k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009]
#        k = [0.1472, 0.1638, 2.1041, 1.8156, 3.8141, 11.6808]
#        k = [0.1784, 0.1365, 2.1201, 1.8057, 3.8071, 11.7009]
#        k = [0.1783,  0.1366,  2.1283,  1.8073,  3.8325, 11.7176]
#        k = [0.25840,  0.14474,  2.22410,  1.92550, 11.59984,  3.92623]
        airfoil = construct_airfoil(*k)
        x, y = get_coords_plain(airfoil._spline(100))
        self.xf.airfoil = Airfoil(x=x, y=y)
        #        test_airfoil = NACA4(2, 3, 15)
#        a = test_airfoil.max_thickness()
#        self.xf.airfoil = test_airfoil.get_coords()
        self.xf.Re = 1e6
        self.xf.M = 0.04
        self.xf.print = False
        cl, cd, cm, cp = self.xf.a(9)
        x = np.array(x, dtype='float32')
        y = np.array(y,dtype='float32')
#        reward = cl/cd
        reward = cl
        ''' 測試結束, 可省略測試'''


#        cl, cd, cm, cp = self.xf.a(12.2357)
#        self.action_space = spaces.Discrete(30)
        self.action_space = spaces.Box(self.min_action, self.max_action, dtype=np.float32)

#        high = np.array([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0])
        high = np.array([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0])
        self.observation_space = spaces.Box(-high, high, dtype=np.float32) #創建state大小(25,f22機翼,b3cl.cd.aoa)
        self.seed()
        self.viewer = None
        self.state = None
        self.steps_beyond_done = None

    def seed(self, seed=None):
        self.np_random, seed = seeding.np_random(seed)
        return [seed]

    def step(self, action):
#        assert self.action_space.contains(action), "%r (%s) invalid"%(action, type(action))
        ''' action 包含 6 個機翼形狀控制參數以及 1 個攻角'''
        angular = action[6]
        k = action[0:6]
        '''將機翼控制座標傳入 airfoil, 並計算翼面之座標'''
        airfoil = construct_airfoil(*k)
        x, y = get_coords_plain(airfoil._spline(100))

        '''將座標傳入 xfoil '''
        self.xf.airfoil = Airfoil(x=x, y=y)
#        state = self.state
        self.xf.Re = 1e6
        self.xf.M = 0.04
        '''計算 cl, cd, cm, cp 當角度為 angular 時'''
        cl, cd, cm, cp = self.xf.a(angular)

        '''如果結果不穩定, 有無限大之值, 重設 state'''
        if np.isnan(cl) or np.isnan(cd) or np.isnan(cm) or np.isnan(cp):
            reward = -10.0
#            self.state = self.reset()
            done = 0
        else:
            '''如果結果穩定, 結束這個 weight 的計算'''

            '''升力最佳或升阻比最佳在此設定'''
#            reward = cl/cd
            reward = cl
            '''從機翼座標裡抽取 11 點當作 state'''
            x1, y1 = get_coords_plain(airfoil._spline(6))
            '''state : 22 個機翼形狀值, 1 個角度, 1 個 cl, cd'''
#            self.state = np.append(np.append(np.append(np.append(x1, y1),angular), cl), cd)
#            self.state = np.append(np.append(x1, y1),angular)
            self.state = np.append(x1, y1)
            done = 1

        return np.array(self.state), reward, done, {}


    def step1(self, action):
        #        assert self.action_space.contains(action), "%r (%s) invalid"%(action, type(action))
        angular = action[6]
        k = action[0:6]
        airfoil = construct_airfoil(*k)
        x, y = get_coords_plain(airfoil._spline(100))
        x1, y1 = get_coords_plain(airfoil._spline(6))
        self.xf.airfoil = Airfoil(x=x, y=y)
        #        state = self.state
        self.xf.Re = 1e6
        self.xf.M = 0.04
        cl, cd, cm, cp = self.xf.a(angular)
        if np.isnan(cl) or np.isnan(cd) or np.isnan(cm) or np.isnan(cp):
#            reward = np.nan
            reward = -10
#            self.state = self.reset()
            done = 0
        else:
#            reward = cl/cd
            reward = cl
            done = 1
#            self.state = np.append(np.append(np.append(np.append(x1, y1),angular), cl), cd)
#            self.state = np.append(np.append(x1, y1),angular)
            self.state = np.append(x1, y1)

        return np.array(self.state), reward, done, x, y

    def reset(self):
#        (.01, .4), (.05, .4), (1, 3), (0.05, 3), (0.4, 8), (1, 10)
#        0.08813299, 0.28250898, 2.80168427, 2.56204214, 1.48703742, 8.53824561
        '''為了避免 state 有無窮大的值, 所以設定decays範圍'''
#        decays = [1.0, 0.5, 0.25, 0.125, 0.0625]
        decays = [1.0, 0.999, 0.995, 0.99, 0.95, 0.9, 0.5]
        for decay in decays:
            tmp1 = self.np_random.uniform(low=-1.0, high=1.0, size=(7,))
#        tmp = tmp * [0.39, 0.35, 2.0, 2.95, 7.6, 9, 10] + [0.01, 0.05, 1, 0.05, 0.4, 1, 0]
#        tmp = tmp * [0.01, 0.1, 0.5, 0.5, 0.1, 1.0, 5] + [0.08813299, 0.28250898, 2.50168427, 2.56, 1.487, 8.54, 0]

        # k = [0.1584, 0.1565, 2.1241, 1.8255, 3.827, 11.6983]
            '''從標準NACA5410開始找'''
            tmp1 = tmp1 * decay
            tmp = tmp1 * [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 5] + [0.1584, 0.1565, 2.1241, 1.8255, 11.6983, 3.827, 6]
            airfoil = construct_airfoil(*tmp)
            x, y = get_coords_plain(airfoil._spline(100))
            self.xf.airfoil = Airfoil(x=x, y=y)
            self.xf.Re = 1e6
            self.xf.M = 0.04
            cl, cd, cm, cp = self.xf.a(tmp[6])
            if not np.isnan(cl):
                break

        x, y = get_coords_plain(airfoil._spline(6))
        self.xf.Re = 1e6
        self.xf.M = 0.04
#        self.state = np.append(np.append(np.append(np.append(x, y), tmp1[6]), cl), cd)
#        self.state = np.append(np.append(x, y), tmp1[6])
        self.state = np.append(x, y)
        self.steps_beyond_done = None
        return np.array(self.state)

    def render(self, mode='human'):

        return None

    def close(self):
        if self.viewer:
            self.viewer.close()
            self.viewer = None
コード例 #30
0
if __name__ == "__main__":

    t0 = time.perf_counter()

    #TODO: CST airfoil for Xfoil
    cst_u = [ 0.135283,  0.088574,  0.177210,  0.080000,  0.231590,  0.189572,  0.192000]
    cst_l = [-0.101390, -0.007993, -0.240000, -0.129790, -0.147840, -0.000050,  0.221251]
    xx, yu, yl, t0, R0 = cst_foil(101, np.array(cst_u), np.array(cst_l), x=None, t=0.0954, tail=0.002)

    x = np.concatenate((np.flip(xx[1:]), xx[1:]), axis=0)
    y = np.concatenate((np.flip(yu[1:]), yl[1:]), axis=0)
    foil = Airfoil(x, y)

    #TODO: Xfoil
    xf = XFoil()
    xf.print = False
    xf.max_iter = 40
    xf.airfoil = foil
    xf.xtr = [0.0, 0.0]

    Minf = 0.2
    AoA  = 8.0
    Re   = 1e7
    fname = 'feature-xfoil.txt'

    xf.M = Minf
    xf.Re = Re

    cl, cd, cm, cp = xf.a(AoA)
    x, cp = xf.get_cp_distribution()