예제 #1
0
    def shape_difference(inputs, optimize_deltaz=False):

        if optimize_deltaz == True or optimize_deltaz == [True]:
            y_u = CST(upper['x'],
                      1,
                      deltasz=inputs[-1] / 2.,
                      Au=list(inputs[:n + 1]))
            y_l = CST(lower['x'],
                      1,
                      deltasz=inputs[-1] / 2.,
                      Al=list(inputs[n + 1:-1]))
        else:
            y_u = CST(upper['x'],
                      1,
                      deltasz=deltaz / 2.,
                      Au=list(inputs[:n + 1]))
            y_l = CST(lower['x'],
                      1,
                      deltasz=deltaz / 2.,
                      Al=list(inputs[n + 1:]))
        # Vector to be compared with
        a_u = {'x': upper['x'], 'y': y_u}
        a_l = {'x': lower['x'], 'y': y_l}

        b_u = upper
        b_l = lower
        return hausdorff_distance_2D(a_u, b_u) + hausdorff_distance_2D(
            a_l, b_l)
예제 #2
0
def calculate_spar_distance(psi_baseline, Au_baseline, Au_goal, Al_goal,
                            deltaz, c_goal):
    """Calculate spar distance (dimensional)"""
    def f(psi_lower_goal):
        y_lower_goal = CST(psi_lower_goal * c_goal, c_goal,
                           [deltaz / 2., deltaz / 2.], Au_goal, Al_goal)
        y_lower_goal = y_lower_goal['l']
        return psi_upper_goal + (s[0] / s[1]) * (y_lower_goal -
                                                 y_upper_goal) / c_goal

    # Calculate cruise chord
    c_baseline = calculate_c_baseline(c_goal, Au_baseline, Au_goal, deltaz)

    # Calculate upper psi at goal airfoil
    psi_upper_goal = calculate_psi_goal(psi_baseline, Au_baseline, Au_goal,
                                        deltaz, c_baseline, c_goal)
    y_upper_goal = CST(psi_upper_goal * c_goal, c_goal,
                       [deltaz / 2., deltaz / 2.], Au_goal, Al_goal)
    y_upper_goal = y_upper_goal['u']

    # Spar direction
    s = calculate_spar_direction(psi_baseline, Au_baseline, Au_goal, deltaz,
                                 c_goal)

    # Calculate lower psi and xi at goal airfoil
    #Because the iterative method can lead to warningdivision by zero after converging, we ignore
    #the warning
    np.seterr(divide='ignore', invalid='ignore')
    psi_lower_goal = optimize.fixed_point(
        f, [psi_upper_goal])  #, args=(c_L, Au_C, Au_L, deltaz)
    x_lower_goal = psi_lower_goal * c_goal
    y_lower_goal = CST(x_lower_goal, c_goal, [deltaz / 2., deltaz / 2.],
                       Au_goal, Al_goal)
    y_lower_goal = y_lower_goal['l']

    return (y_upper_goal - y_lower_goal[0]) / s[1]
예제 #3
0
min_x = min(raw_data['x'])
min_index = raw_data['x'].index(min_x)
min_y = raw_data['y'][min_index]

chord = max(raw_data['x']) - min(raw_data['x'])
beta = math.atan((y_TE - min_y) / (x_TE - min_x))

for i in range(len(raw_data['x'])):
    processed_data['x'].append((raw_data['x'][i] - min_x) / chord)
    processed_data['y'].append(raw_data['y'][i] / chord)
raw_data = processed_data

psi = np.linspace(0, 1, 200)
xi = CST(psi,
         1., [data['deltaz'][n - 1] / 2., data['deltaz'][n - 1] / 2.],
         Au=data['Au'][n - 1],
         Al=data['Al'][n - 1])
plt.figure()
plt.plot(psi, xi['u'], psi, xi['l'])
plt.scatter(raw_data['x'], raw_data['y'])
n = 8
plt.xlim(0, 1)
x = np.linspace(2, 2 * n, n)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()

plt.figure()
plt.plot(x, data['error'])
plt.scatter(x, data['error'])
plt.xlabel('Number of shape functions')
plt.ylabel('Hausdorff distance (adimensional)')
예제 #4
0
    # tracing :
    A = calculate_shape_coefficients_tracing(AC_u0, ValX, ValY, 0.5, 1.,c_C, deltaz)
    # structurally_consistent :
    Au_C, Al_C, c_C, spar_thicknesses = calculate_dependent_shape_coefficients(
                                                        A[1:], psi_spars, Au_P, Al_P,
                                                        deltaz, c_P, morphing=morphing_direction)
    error = abs((AC_u0-Au_C[0])/AC_u0) 
    print 'Iteration: ' + str(counter) + ', Error: ' +str(error)
    AC_u0 = Au_C[0]
    counter += 1

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plotting :
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x = np.linspace(0, c_C, 1000)
y = CST(x, c_C, deltasz= [deltaz/2., deltaz/2.],  Al= Al_C, Au =Au_C)
plt.plot(x, y['u'],'b',label = 'Children', lw=2)
plt.plot(x, y['l'],'b',label = None, lw=2)

# Print shape for parent
x = np.linspace(0, c_P, 1000)
y = CST(x, c_P, deltasz= [deltaz/2., deltaz/2.],  Al= Al_P, Au =Au_P)
plt.plot(x, y['u'],'r--',label='Parent', lw=2)
plt.plot(x, y['l'],'r--',label = None, lw=2)

if morphing_direction == 'forwards':
	psi_flats = []
	intersections_x_children = [0]
	intersections_y_children = [0]
	intersections_x_parent = [0]
	intersections_y_parent = [0]
예제 #5
0
import numpy as np
import matplotlib.pyplot as plt

import xfoil_module as xf
from CST_module import *
from aero_module import Reynolds
from airfoil_module import CST, create_x

# Au = [0.23993240191629417, 0.34468227138908186, 0.18125405377549103,
# 0.35371349126072665, 0.2440815012119143, 0.25724974995738387]
# Al = [0.18889012559339036, -0.24686758992053115, 0.077569769493868401,
# -0.547827192265256, -0.0047342206759065641, -0.23994805474814629]
Au = [0.172802, 0.167353, 0.130747, 0.172053, 0.112797, 0.168891]
Al = Au
# c_avian = 0.36                  #m
# deltaz = 0.0093943568219451313*c_avian
c_avian = 1.
deltaz = 0

airfoil = 'avian'
x = create_x(1., distribution='linear')
y = CST(x, 1., [deltaz / 2., deltaz / 2.], Au=Au, Al=Al)
# Create file for Xfoil to read coordinates
xf.create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower=False)
print 'Reynolds: ', Reynolds(10000, 30, c_avian)
Data = xf.find_coefficients(airfoil,
                            0.,
                            Reynolds=Reynolds(10000, 30, c_avian),
                            iteration=100,
                            NACA=False)
print Data
예제 #6
0
def calculate_dependent_shape_coefficients(Au_C_1_to_n,
                                           psi_spars,
                                           Au_P,
                                           Al_P,
                                           deltaz,
                                           c_P,
                                           morphing='backwards'):
    """Calculate  dependent shape coefficients for children configuration for a 4 order
    Bernstein polynomial and return the children upper, lower shape 
    coefficients, children chord and spar thicknesses. _P denotes parent parameters"""
    def calculate_AC_u0(AC_u0):
        Au_C = [AC_u0] + Au_C_1_to_n
        c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz)
        return np.sqrt(c_P / c_C) * Au_P[0]

    # Bersntein Polynomial
    def K(r, n):
        K = math.factorial(n) / (math.factorial(r) * math.factorial(n - r))
        return K

    # Bernstein Polynomial order
    n = len(Au_C_1_to_n)

    # Find upper shape coefficient though iterative method since Au_0 is unknown
    # via fixed point iteration
    #AC_u0 = optimize.fixed_point(calculate_AC_u0, Au_P[0])
    #print AC_u0
    error = 9999
    AC_u0 = Au_P[0]
    while error > 1e-9:
        before = AC_u0
        AC_u0 = calculate_AC_u0(AC_u0)
        error = abs(AC_u0 - before)

    # Because the output is an array, need the extra [0]
    Au_C = [AC_u0] + Au_C_1_to_n

    # Now that AC_u0 is known we can calculate the actual chord and AC_l0
    c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz / c_P)
    AC_l0 = np.sqrt(c_P / c_C) * Al_P[0]
    # print '0 lower shape coefficient: ',AC_l0
    # Calculate thicknessed and tensor B for the constraint linear system problem
    spar_thicknesses = []
    A0 = AC_u0 + AC_l0

    if morphing == 'backwards':
        b_list = np.zeros((n, 1))
        for j in range(len(psi_spars)):
            psi_j = psi_spars[j]
            #Calculate the spar thickness in meters from parent, afterwards, need to
            #adimensionalize for the goal airfoil by dividing by c_goal
            t_j = calculate_spar_distance(psi_spars[j], Au_C, Au_P, Al_P,
                                          deltaz, c_P)

            spar_thicknesses.append(t_j)
            b_list[j] = (t_j / c_C - psi_j * deltaz / c_C) / (
                (psi_j**0.5) * (1 - psi_j)) - A0 * (1 - psi_j)**n

        B = np.zeros((n, n))
        #j is the row dimension and i the column dimension in this case
        for j in range(n):
            for i in range(n):
                #Because in Python counting starts at 0, need to add 1 to be
                #coherent for equations
                r = i + 1
                B[j][i] = K(r, n) * (psi_spars[j]**
                                     r) * (1 - psi_spars[j])**(n - r)

        A_bar = np.dot(inv(B), b_list)

        Al_C = [AC_l0]
        for i in range(len(A_bar)):
            Al_C.append(A_bar[i][0] -
                        Au_C[i + 1])  #extra [0] is necessary because of array

    elif morphing == 'forwards':
        f = np.zeros((n, 1))
        # psi/xi coordinates for lower surface of the children configuration
        psi_lower_children = []
        xi_lower_children = []
        xi_upper_children = []

        c_C = calculate_c_baseline(c_P, Au_C, Au_P, deltaz)
        # psi_baseline, Au_baseline, Au_goal, deltaz, c_baseline, c_goal
        psi_upper_children = []
        for j in range(len(psi_spars)):
            psi_upper_children.append(
                calculate_psi_goal(psi_spars[j], Au_P, Au_C, deltaz, c_P, c_C))
        # Calculate xi for upper children. Do not care about lower so just gave it random shape coefficients
        xi_upper_children = CST(psi_upper_children,
                                1.,
                                deltasz=[deltaz / 2. / c_C, deltaz / 2. / c_C],
                                Al=Au_C,
                                Au=Au_C)
        xi_upper_children = xi_upper_children['u']

        # print xi_upper_children

        #Debugging section
        x = np.linspace(0, 1)
        y = CST(x,
                1.,
                deltasz=[deltaz / 2. / c_C, deltaz / 2. / c_C],
                Al=Au_C,
                Au=Au_C)
        # plt.plot(x,y['u'])
        # plt.scatter(psi_upper_children, xi_upper_children)
        # plt.grid()
        # plt.show()
        # BREAK
        for j in range(len(psi_spars)):
            xi_parent = CST(psi_spars,
                            1.,
                            deltasz=[deltaz / 2. / c_P, deltaz / 2. / c_P],
                            Al=Al_P,
                            Au=Au_P)
            delta_j_P = xi_parent['u'][j] - xi_parent['l'][j]
            t_j = c_P * (delta_j_P)
            # Claculate orientation for children
            s_j = calculate_spar_direction(psi_spars[j], Au_P, Au_C, deltaz,
                                           c_C)
            psi_l_j = psi_upper_children[j] - delta_j_P / c_C * s_j[0]
            xi_l_j = xi_upper_children[j] - delta_j_P / c_C * s_j[1]

            spar_thicknesses.append(t_j)
            psi_lower_children.append(psi_l_j)
            xi_lower_children.append(xi_l_j)

            f[j] = (2 * xi_l_j + psi_l_j * deltaz / c_C) / (
                2 * (psi_l_j**0.5) * (psi_l_j - 1)) - AC_l0 * (1 - psi_l_j)**n

        F = np.zeros((n, n))
        #j is the row dimension and i the column dimension in this case
        for j in range(n):
            for i in range(n):
                #Because in Python counting starts at 0, need to add 1 to be
                #coherent for equations
                r = i + 1
                F[j][i] = K(r, n) * (psi_lower_children[j]**
                                     r) * (1 - psi_lower_children[j])**(n - r)
        # print F
        # print f
        A_lower = np.dot(inv(F), f)

        Al_C = [AC_l0]
        for i in range(len(A_lower)):
            Al_C.append(
                A_lower[i][0])  #extra [0] is necessary because of array
    return Au_C, Al_C, c_C, spar_thicknesses
예제 #7
0
            if y_i >= tip_displacement['y']:
                print 'Y value out of bounds!'
        A = calculate_shape_coefficients_tracing(
            A0,
            other_points['y'],
            other_points['x'],
            N1,
            N2,
            chord=tip_displacement['y'],
            EndThickness=tip_displacement['x'])

        #plotting
        y = np.linspace(0, tip_displacement['y'], 100000)
        x = CST(y,
                tip_displacement['y'],
                deltasz=tip_displacement['x'],
                Au=A,
                N1=N1,
                N2=N2)
        plt.plot(x, y)
        plt.scatter(other_points['x'] + [tip_displacement['x']],
                    other_points['y'] + [tip_displacement['y']])
        plt.gca().set_aspect('equal', adjustable='box')
        plt.show()

    elif testing == 'structurally_consistent':

        #==============================================================================
        # Inputs
        #==============================================================================
        # Parameter
        c_P = 1.  #m
예제 #8
0
def calculate_average_camber(Au, Al, delta_xi):
    psi = np.linspace(0, 1, 1000)
    xi = CST(psi, 1., [delta_xi / 2., delta_xi / 2.], Au, Al)
    camber = (xi['u'] + xi['l']) / 2.
    return np.average(np.absolute(camber))
예제 #9
0
def calculate_camber(psi, Au, Al, delta_xi):
    xi = CST(psi, 1., [delta_xi / 2., delta_xi / 2.], Au, Al)
    return (xi['u'] + xi['l']) / 2.
예제 #10
0
 def f(psi_lower_goal):
     y_lower_goal = CST(psi_lower_goal * c_goal, c_goal,
                        [deltaz / 2., deltaz / 2.], Au_goal, Al_goal)
     y_lower_goal = y_lower_goal['l']
     return psi_upper_goal + (s[0] / s[1]) * (y_lower_goal -
                                              y_upper_goal) / c_goal
예제 #11
0
        Au_C[0] = x_i
        c_i = calculate_c_baseline(c_L, Au_C, Au_L, deltaz)
        c.append(c_i)
    plt.plot(x, c)
    plt.xlabel('$A_{u_0}^C$', fontsize=20)
    plt.ylabel('$c^C$', fontsize=20)
    plt.grid()
    plt.show()

    # Plot airfoils for different Au
    plt.figure()
    psi = np.linspace(0, 1, 500)
    i = 0
    for c_i in c:
        Au_C[0] = x[i]
        y = CST(psi, 1, [deltaz / 2., deltaz / 2.], Au_C, Al_C)
        x_plot = np.linspace(0, c_i, 500)
        plt.plot(x_plot, c_i * y['u'], label='$A_{u_0}$ = %.1f' % x[i])
        y_psi = CST(psi_i, 1, [deltaz / 2., deltaz / 2.], Au_C, Al_C)
        i += 1
    plt.xlabel(r'$\psi^C$', fontsize=20)
    plt.ylabel(r'$\xi^C$', fontsize=20)
    plt.legend()
    plt.show()

    # Plot for several testing calculat_psi_goal
    plt.figure()
    x = np.linspace(0., 1., 11)
    psi_goal_list = []
    for x_i in x:
        Au_C[0] = x_i
예제 #12
0
def CST_3D(Bu, Bl, span, N={'eta':[0,1], 'N1':[.5, .5], 'N2':[1., 1.], 'chord':[1., 0]},
           mesh = (100,100), chord = {'eta':[0,1], 'A':[1.], 'N1':1, 'N2':1, 'initial_chord':1.}, 
           sweep = {'eta':[0,1], 'A':[1.], 'N1':1, 'N2':1, 'initial_chord':1., 'x_LE_initial':0}):
    """
    - Bu: upper shape coefficients
    - Bl: lower shape coefficients
    - mesh: list of number of points in x and y
    """
    def S(B, psi, eta):
        """ Cross section shape function. Validated for high dimensions.
           To debug just verify if it turns all ones when B=ones"""
        def S_i(r, n, psi):
            """Shape function"""
            value = K(r,n)*(psi**r)*(1.-psi)**(n-r)
            return value

        # Bersntein Polynomial
        def K(r,n):
            K=math.factorial(n)/(math.factorial(r)*math.factorial(n-r))
            return K

        Nx = len(B)-1
        Ny = len(B[0])-1

        output = 0
        for i in range(Nx+1):
            for j in range(Ny+1):
                output += B[i][j]*S_i(i, Nx, psi)*S_i(j, Ny, eta)
        return output

    def C(N, psi, eta):
        """Class function"""
        N1 = interp1d(N['eta'], N['N1'])
        N2 = interp1d(N['eta'], N['N2'])
        output = ((psi)**N1(eta))*((1.-psi)**N2(eta))
        return output

    psi = np.linspace(0,1,mesh[0])
    eta = np.linspace(0,1,mesh[1])

    zeta_u = np.zeros(mesh)
    zeta_l = np.zeros(mesh)
    for i in range(mesh[0]):
        for j in range(mesh[1]):
            zeta_u[j][i] = C(N, psi[i], eta[j])*S(Bu, psi[i], eta[j])
            zeta_l[j][i] = -C(N, psi[i], eta[j])*S(Bl, psi[i], eta[j])
    print eta
    print chord['initial_chord']
    print chord['A']
    print chord['N1'], chord['N2']
    chord_distribution = CST(eta, chord['eta'][1], chord['initial_chord'], Au=chord['A'], N1=chord['N1'], N2=chord['N2'])
    sweep_distribution = CST(eta, sweep['eta'][1], sweep['x_LE_initial'], Au=sweep['A'], N1=sweep['N1'], N2=sweep['N2'])
    chord_distribution = chord_distribution[::-1]
    sweep_distribution = sweep_distribution
    # taper_function(eta, shape = 'linear', N)
    x = np.zeros(len(psi))
    for i in range(len(x)):
        x[i] = psi[i]*chord_distribution[i]
    print chord_distribution
    print x
    print psi
    y = eta

    X = np.zeros(mesh)
    Y = np.zeros(mesh)
    Z_u = np.zeros(mesh)
    Z_l = np.zeros(mesh)
    for i in range(mesh[0]):
        for j in range(mesh[1]):
            X[j][i] = psi[i]*chord_distribution[j] + .5*sweep_distribution[j]
            Y[j][i] = span*eta[j]
            Z_u[j][i] = zeta_u[j][i]*chord_distribution[j]
            Z_l[j][i] = zeta_l[j][i]*chord_distribution[j]
    return [X,Y,Z_u,Z_l]
예제 #13
0
            Y[j][i] = span*eta[j]
            Z_u[j][i] = zeta_u[j][i]*chord_distribution[j]
            Z_l[j][i] = zeta_l[j][i]*chord_distribution[j]
    return [X,Y,Z_u,Z_l]

if __name__ == '__main__':
    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    from matplotlib import cm

    # B = [[1,1], [1.,1]]
    B = [[1], [1]]
    x = np.linspace(0,1)
    initial_chord = .5
    span = 4.
    chord_distribution = CST(x, initial_chord, span, Au=[1.], Al=None, N1=1., N2=1.)
    
    [X,Y,Z_u, Z_l] = CST_3D(B, B, mesh =(50,50), span=span,
                            N={'eta':[0,1], 'N1':[.5, .5], 'N2':[.5, .5]},
                            chord = {'eta':[0,1], 'A':[1.], 'N1':1., 'N2':1, 'initial_chord':1.},
                            sweep = {'eta':[0,1], 'A':[1.], 'N1':1, 'N2':1., 'initial_chord':1., 'x_LE_initial':-2})

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    surf_u = ax.plot_surface(X, Z_u, Y, cmap=plt.get_cmap('jet'),
                       linewidth=0, antialiased=False)
    surf_l = ax.plot_surface(X, Z_l, Y, cmap=plt.get_cmap('jet'),
                       linewidth=0, antialiased=False)
    # cset = ax.contour(X, Z_u, Y, zdir='z', offset=0, cmap=cm.coolwarm)
    # cset = ax.contour(X, Z_l, Y, zdir='z', offset=0,  cmap=cm.coolwarm)
    # cset = ax.contour(X, Z_u, Y, zdir='x', offset=-.1, cmap=cm.coolwarm)
예제 #14
0
from airfoil_module import CST, create_x

Au = [
    0.23993240191629417, 0.34468227138908186, 0.18125405377549103,
    0.35371349126072665, 0.2440815012119143, 0.25724974995738387
]
Al = [
    0.18889012559339036, -0.24686758992053115, 0.077569769493868401,
    -0.547827192265256, -0.0047342206759065641, -0.23994805474814629
]
c_avian = .36  #m
deltaz = 0.0093943568219451313 * c_avian

airfoil = 'avian'
x = create_x(c_avian, distribution='linear')
y = CST(x, c_avian, [deltaz / 2., deltaz / 2.], Au=Au, Al=Al)
# Create file for Xfoil to read coordinates
xf.create_input(x, y['u'], y['l'], airfoil, different_x_upper_lower=False)

Data = xf.find_coefficients(airfoil,
                            2.,
                            Reynolds=Reynolds(10000, 30, c_avian),
                            iteration=100,
                            NACA=False)
print Data

psi_u_inflection, psi_l_inflection = find_inflection_points(Au, Al)
print 'upper: ', psi_u_inflection
print 'lower: ', psi_l_inflection
psi = np.linspace(0.001, 0.999, 100)
xi = CST(psi, 1, [deltaz / 2., deltaz / 2.], Au, Al)