Example #1
0
def hello():
    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.Re = Re
    xf.M = 0
    xf.max_iter = 100
    xf.airfoil = Airfoil(np.array(bezierX), np.array(bezierY))
    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(bezierX, bezierY)

    print(len(xcp))

    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())
Example #2
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
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 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
Example #5
0
    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]
Example #6
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
Example #7
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)
Example #8
0
    #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()

    with open(fname, 'w') as f:
        f.write('%10s   %15.6f \n'%('Minf', Minf))
        f.write('%10s   %15.6f \n'%('AoA', AoA))
        f.write('%10s   %15.6f \n'%('Re', Re/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))

    fF = PhysicalXfoil(Minf, AoA, Re)
    fF.setdata(x,y,cp)
    fF.extract_features()
    fF.output_features(fname=fname, append=True)