def z_final_force_distribution(y, length_step, density, velocity):
    value = lift_distribution(
        y, length_step, density, velocity
    ) - weight_wing / surface_area * aerodynamic_data.chord_function(y)
    if ((fuel_tank_start < y < fuel_tank_engine_stop) or
        (fuel_tank_engine_start < y < fuel_tank_stop)) and include_fuel_tanks:
        value -= (weight_fuel / fuel_tank_length) * fuel_tank_level
    if spanwise_location_engine - length_step / 2 < y < spanwise_location_engine + length_step / 2 and include_engine:
        value -= weight_engine
    return value
def shearflow_doublecell(spanwise_location):
    centroid = get_centroid(spanwise_location)

    # PROGRAM FROM REINIR TO GET STRINGER LOCATIONS
    wingbox_corner_points = database_connector.load_wingbox_value(
        'wingbox_corner_points')

    def get_location(end_points):
        # Input end_points as [[x1,y1], [x2,y2]]
        return [(end_points[0][0] + end_points[1][0]) / 2 - centroid[0],
                (end_points[0][1] + end_points[1][1]) / 2 - centroid[1]]

    def get_length(end_points):
        # Input end_points as [[x1,y1], [x2,y2]]
        return ((end_points[0][0] - end_points[1][0])**2 +
                (end_points[0][1] - end_points[1][1])**2)**0.5

    # Get all plate dimensions by rearranging corner points
    leading_spar_chord = [[
        wingbox_corner_points[0][0], wingbox_corner_points[0][1]
    ], [wingbox_corner_points[3][0], wingbox_corner_points[3][1]]]
    trailing_spar_chord = [[
        wingbox_corner_points[1][0], wingbox_corner_points[1][1]
    ], [wingbox_corner_points[2][0], wingbox_corner_points[2][1]]]
    leading_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in leading_spar_chord
    ]
    trailing_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in trailing_spar_chord
    ]
    # leading_spar_location = get_location(leading_spar)
    # trailing_spar_location = get_location(trailing_spar)
    # leading_spar_length = get_length(leading_spar)
    # trailing_spar_length = get_length(trailing_spar)
    spar_thickness = database_connector.load_wingbox_value('spar_thickness')

    top_plate_chord = [[
        wingbox_corner_points[0][0], wingbox_corner_points[0][1]
    ], [wingbox_corner_points[1][0], wingbox_corner_points[1][1]]]
    bottom_plate_chord = [[
        wingbox_corner_points[2][0], wingbox_corner_points[2][1]
    ], [wingbox_corner_points[3][0], wingbox_corner_points[3][1]]]
    top_plate = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in top_plate_chord
    ]
    bottom_plate = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in bottom_plate_chord
    ]
    # top_plate_location = get_location(top_plate)
    # bottom_plate_location = get_location(bottom_plate)
    # top_plate_length = get_length(top_plate)
    # bottom_plate_length = get_length(bottom_plate)
    plate_thickness = database_connector.load_wingbox_value('plate_thickness')

    # Get stringer locations along the top and bottom plate:
    stringer_top_locations = np.transpose([
        np.linspace(top_plate[0][0], top_plate[1][0],
                    get_amount_of_stringers(spanwise_location, True)),
        np.linspace(top_plate[0][1], top_plate[1][1],
                    get_amount_of_stringers(spanwise_location, True))
    ])
    stringer_top_distance_from_centroid = stringer_top_locations - centroid
    stringer_bottom_locations = np.transpose([
        np.linspace(bottom_plate[0][0], bottom_plate[1][0],
                    get_amount_of_stringers(spanwise_location, False)),
        np.linspace(bottom_plate[0][1], bottom_plate[1][1],
                    get_amount_of_stringers(spanwise_location, False))
    ])
    stringer_bottom_distance_from_centroid = stringer_bottom_locations - centroid

    # END OF PROGRAM FROM REINIER

    # importing the loading data
    try:
        with open("./data.pickle", 'rb') as file:
            data = pickle.load(file)
    except FileNotFoundError:
        with open("../InertialLoadingCalculator/data.pickle", 'rb') as file:
            data = pickle.load(file)
    y_span_lst = data[0]

    # TORQUE
    torsion_lst = data[7]
    torsion = sp.interpolate.interp1d(y_span_lst,
                                      torsion_lst,
                                      kind="cubic",
                                      fill_value="extrapolate")
    torque_y = torsion(spanwise_location)

    # positive z is downwards
    # LIFT
    lift_lst = data[2]
    v_force = sp.interpolate.interp1d(y_span_lst,
                                      lift_lst,
                                      kind="cubic",
                                      fill_value="extrapolate")
    v_force_y = v_force(spanwise_location)

    # DRAG
    drag_lst = data[5]
    h_force = sp.interpolate.interp1d(y_span_lst,
                                      drag_lst,
                                      kind="cubic",
                                      fill_value="extrapolate")
    h_force_y = h_force(spanwise_location)

    # importing constants
    G = database_connector.load_wingbox_value("shear_modulus_pa")
    wingbox_points = database_connector.load_wingbox_value("wingbox_points")
    area_bottom_stringer = database_connector.load_wingbox_value(
        "bottom_stringer_area")
    area_top_stringer = database_connector.load_wingbox_value(
        "top_stringer_area")

    # thicknesses of spar and plates for torque calculations
    t_12 = t_23 = t_45 = t_56 = database_connector.load_wingbox_value(
        "plate_thickness")
    t_34 = t_61 = t_25 = database_connector.load_wingbox_value(
        "spar_thickness")

    # PROCESSING OF RELEVANT DATA FOR SHEAR DUE TO TORQUE CALCULATIONS
    # the 6 points are numbered from 1 to 6 from top left to bottom left in clockwise direction
    distances_1 = (wingbox_points[0][0] - centroid[0],
                   wingbox_points[0][1] - centroid[1])
    distances_2 = (wingbox_points[1][0] - centroid[0],
                   wingbox_points[1][1] - centroid[1])
    distances_3 = (wingbox_points[2][0] - centroid[0],
                   wingbox_points[2][1] - centroid[1])
    distances_4 = (wingbox_points[3][0] - centroid[0],
                   wingbox_points[3][1] - centroid[1])
    distances_5 = (wingbox_points[4][0] - centroid[0],
                   wingbox_points[4][1] - centroid[1])
    distances_6 = (wingbox_points[5][0] - centroid[0],
                   wingbox_points[5][1] - centroid[1])

    chord_length = aerodynamic_data.chord_function(spanwise_location)

    length_12 = abs(distances_1[0] - distances_2[0]) * chord_length
    length_23 = abs(distances_2[0] - distances_3[0]) * chord_length
    length_34 = abs(distances_3[1] - distances_4[1]) * chord_length
    # length_45 = abs(distances_4[0] - distances_5[0]) * chord_length
    # length_56 = abs(distances_5[0] - distances_6[0]) * chord_length
    length_61 = abs(distances_6[1] - distances_1[1]) * chord_length
    length_25 = abs(distances_2[1] - distances_5[1]) * chord_length

    encl_area_1256 = (length_25 + length_61) * length_12 / 2
    encl_area_2345 = (length_25 + length_34) * length_23 / 2

    # PROCESSING OF RELEVANT DATA FOR SHEAR DUE TO VERTICAL FORCE CALCULATIONS
    # q_b calculations for each boom
    MoI_xx = area_top_stringer * (distances_1[1] ** 2 + distances_2[1] ** 2 + distances_3[1] ** 2) \
             + area_bottom_stringer * (distances_4[1] ** 2 + distances_5[1] ** 2 + distances_6[1] ** 2)
    MoI_yy = area_top_stringer * (distances_1[0] ** 2 + distances_2[0] ** 2 + distances_3[0] ** 2) \
             + area_bottom_stringer * (distances_4[0] ** 2 + distances_5[0] ** 2 + distances_6[0] ** 2)

    # The integral term for Lorezno
    def q_b(distance_from_centroid, area):
        return - (MoI_xx * h_force_y) / (MoI_xx * MoI_yy) * (area * distance_from_centroid[0]) - \
               (MoI_yy * v_force_y) / (MoI_xx * MoI_yy) * (area * distance_from_centroid[1])

    # BOTTOM FLANGES q_b
    # q_b for the first cell (two flanges)
    q_b_16 = q_b(distances_1, area_top_stringer)

    integral_value_front_bottom = q_b_16
    q_b_lst_bottom_surface_frontcell = []
    # Bottom stringers of front cell (Change as you see fit Lorezno)
    for stringer_index in range(
            0, int(round(len(stringer_bottom_distance_from_centroid) / 2))):
        integral_value_front_bottom += (
            q_b(stringer_bottom_distance_from_centroid[stringer_index],
                area_bottom_stringer) * get_length([
                    stringer_bottom_locations[stringer_index],
                    stringer_bottom_locations[stringer_index - 1]
                ])) / (plate_thickness * G)
        q_b_lst_bottom_surface_frontcell.append(integral_value_front_bottom)

    # q_b for the second cell (two flanges)
    q_b_25 = q_b(distances_2, area_top_stringer)
    integral_value_aft_bottom = q_b_25
    q_b_lst_bottom_surface_aftcell = []
    # Bottom stringers of aft cell (Change as you see fit)
    for stringer_index in range(
            int(round(len(stringer_bottom_distance_from_centroid) / 2)),
            int(round(len(stringer_bottom_distance_from_centroid)))):
        integral_value_aft_bottom += (
            q_b(stringer_bottom_distance_from_centroid[stringer_index],
                area_bottom_stringer) * get_length([
                    stringer_bottom_locations[stringer_index],
                    stringer_bottom_locations[stringer_index - 1]
                ])) / (plate_thickness * G)
        q_b_lst_bottom_surface_aftcell.append(integral_value_aft_bottom)

    # TOP FLANGES q_b
    integral_value_front_top = q_b_lst_bottom_surface_frontcell[-1]
    q_b_lst_top_surface_frontcell = []
    # Bottom stringers of front cell (Change as you see fit Lorezno)
    for stringer_index in range(
            0, int(round(len(stringer_top_distance_from_centroid) / 2))):
        integral_value_front_top += (
            q_b(stringer_top_distance_from_centroid[stringer_index],
                area_top_stringer) * get_length([
                    stringer_top_locations[stringer_index],
                    stringer_top_locations[stringer_index - 1]
                ])) / (plate_thickness * G)
        q_b_lst_bottom_surface_frontcell.append(integral_value_front_top)

    # q_b for the second cell (two flanges)
    integral_value_aft_top = q_b_lst_bottom_surface_aftcell[-1]
    q_b_lst_top_surface_aftcell = []
    # Bottom stringers of aft cell (Change as you see fit)
    for stringer_index in range(
            int(round(len(stringer_top_distance_from_centroid) / 2)),
            int(round(len(stringer_top_distance_from_centroid)))):
        integral_value_aft_top += (
            q_b(stringer_top_distance_from_centroid[stringer_index],
                area_top_stringer) * get_length([
                    stringer_top_locations[stringer_index],
                    stringer_top_locations[stringer_index - 1]
                ])) / (plate_thickness * G)
        q_b_lst_top_surface_aftcell.append(integral_value_aft_top)

    inter_stringer_distance_bottom = get_length(
        [[0, 0],
         abs(stringer_bottom_distance_from_centroid[0] -
             stringer_bottom_distance_from_centroid[1])])
    inter_stringer_distance_top = get_length(
        [[0, 0],
         abs(stringer_top_distance_from_centroid[0] -
             stringer_top_distance_from_centroid[1])])

    p1 = np.array([centroid[0], centroid[1]])
    p2 = np.array(stringer_bottom_distance_from_centroid[0])
    p3 = np.array(stringer_bottom_distance_from_centroid[1])
    moment_arm_bottom_surface_qbs = np.cross(p2 - p1,
                                             p3 - p1) / np.linalg.norm(p2 - p1)

    # moment generated by qbs and forces around point 2

    ## TO BE CHECKED WITH RASA
    moment_due_to_forces = v_force_y * distances_2[
        0] + h_force_y * distances_2[1]

    ## Direction to be checked
    moment_due_to_bottom_surface_qbs_frontcell = integral_value_front_bottom * \
                                                 length_12 \
                                                 + moment_arm_bottom_surface_qbs * \
                                                 sum(q_b_lst_bottom_surface_frontcell[:-1])
    moment_due_to_bottom_surface_qbs_aftcell = moment_arm_bottom_surface_qbs * \
                                               sum(q_b_lst_bottom_surface_aftcell[:-1]) + \
                                               length_34 * \
                                               q_b_lst_bottom_surface_aftcell[-1]

    total_moment_forces_qbs_allcell = moment_due_to_forces - moment_due_to_bottom_surface_qbs_frontcell - \
                                      moment_due_to_bottom_surface_qbs_aftcell

    # line integrals functional to the equation with dthetha/dz
    # bottom plates
    line_integral_qb_frontcell_bottom = (
        integral_value_front_bottom * length_61 +
        q_b_lst_bottom_surface_frontcell[-1] * length_25) / (t_61 * G)
    for element in q_b_lst_bottom_surface_frontcell[:-1]:
        line_integral_qb_frontcell_bottom += element * inter_stringer_distance_bottom / (
            t_56 * G)
    line_integral_qb_aftcell_bottom = (
        integral_value_aft_bottom * length_25 +
        q_b_lst_bottom_surface_aftcell[-1] * length_34) / (t_25 * G)
    for element in q_b_lst_bottom_surface_aftcell[:-1]:
        line_integral_qb_aftcell_bottom += element * inter_stringer_distance_bottom / (
            t_45 * G)
        # top plates
    line_integral_qb_frontcell_top = 0
    for element in q_b_lst_top_surface_frontcell[:-1]:
        line_integral_qb_frontcell_top += element * inter_stringer_distance_top / (
            t_12 * G)
    line_integral_qb_aftcell_top = 0
    for element in q_b_lst_top_surface_aftcell[:-1]:
        line_integral_qb_aftcell_top += element * inter_stringer_distance_top / (
            t_23 * G)

    dthetha_dz_contribution_qb_frontcell = (line_integral_qb_frontcell_bottom + line_integral_qb_frontcell_top) \
                                           / (2 * encl_area_1256)
    dthetha_dz_contribution_qb_aftcell = (line_integral_qb_aftcell_bottom + line_integral_qb_aftcell_top) \
                                         / (2 * encl_area_1256)

    # Matrix
    matrix = np.array([[2 * encl_area_1256, 2 * encl_area_2345, 0],
                       [
                           1 / (2 * encl_area_1256 * G) *
                           (1 / t_12 + 1 / t_61 + 1 / t_25 + 1 / t_56),
                           1 / (2 * encl_area_1256 * G) * (-1 / t_25), -1
                       ],
                       [
                           1 / (2 * encl_area_2345 * G) * (-1 / t_25),
                           1 / (2 * encl_area_2345 * G) *
                           (1 / t_23 + 1 / t_34 + 1 / t_45 + 1 / t_25), -1
                       ]])

    # SHEAR DUE TO TORQUE
    solution_vector_t = np.array([torque_y, 0, 0])
    q_t_1256, q_t_2345, dtheta_t = np.linalg.solve(matrix, solution_vector_t)

    # SHEAR DUE TO VERTICAL and HORIZONTAL FORCE #tbf
    solution_vector_s = np.array([
        total_moment_forces_qbs_allcell, dthetha_dz_contribution_qb_frontcell,
        dthetha_dz_contribution_qb_aftcell
    ])
    q_s_s0_1256, q_s_s0_2345, dtheta_s = np.linalg.solve(
        matrix, solution_vector_s)

    # TOTAL SHEAR FORCE EVALUATION IN EACH SECTION
    q_max_top_flange_value = 0
    q_max_bottom_flange_value = 0

    # top surface aftcell
    for stringer_index in range(
            int(round(len(stringer_top_distance_from_centroid) / 2)),
            int(round(len(stringer_top_distance_from_centroid)))):
        q_tot = abs(
            q_b(stringer_top_distance_from_centroid[stringer_index],
                area_top_stringer) + q_t_2345 + q_s_s0_2345)
        if q_tot > q_max_top_flange_value:
            q_max_top_flange_value = q_tot
    if abs(q_t_1256 + q_s_s0_1256) > q_max_top_flange_value:
        q_max_top_flange_value = abs(q_t_1256 + q_s_s0_1256)
    if abs(q_t_2345 + q_s_s0_2345) > q_max_top_flange_value:
        q_max_top_flange_value = abs(q_t_2345 + q_s_s0_2345)

    # bottom surface aftcell
    for stringer_index in range(
            int(round(len(stringer_bottom_distance_from_centroid) / 2)),
            int(round(len(stringer_bottom_distance_from_centroid)))):
        q_tot = abs(
            q_b(stringer_bottom_distance_from_centroid[stringer_index],
                area_bottom_stringer) + q_t_2345 + q_s_s0_2345)
        if q_tot > q_max_bottom_flange_value:
            q_max_bottom_flange_value = q_tot

    # top surface frontcell
    for stringer_index in range(
            0, int(round(len(stringer_top_distance_from_centroid) / 2))):
        q_tot = abs(
            q_b(stringer_top_distance_from_centroid[stringer_index],
                area_top_stringer) + q_t_1256 + q_s_s0_1256)
        if q_tot > q_max_top_flange_value:
            q_max_top_flange_value = q_tot

    # bottom surface frontcell
    for stringer_index in range(
            0, int(round(len(stringer_top_distance_from_centroid) / 2))):
        q_tot = abs(
            q_b(stringer_bottom_distance_from_centroid[stringer_index],
                area_bottom_stringer) + q_t_1256 + q_s_s0_1256)
        if q_tot > q_max_bottom_flange_value:
            q_max_bottom_flange_value = q_tot

    # front spar tot shear flow
    q_tot_front_spar = abs(integral_value_front_bottom + q_t_1256 +
                           q_s_s0_1256)

    # middle spar tot shear flow
    q_tot_middle_spar = abs(
        q_b(
            stringer_bottom_distance_from_centroid[int(
                round(len(stringer_bottom_distance_from_centroid) /
                      2))], area_top_stringer) + q_t_1256 + q_s_s0_1256 -
        q_t_2345 - q_s_s0_2345)

    # aft spar tot shear flow
    #q_tot_aft_spar = abs(q_b(stringer_bottom_distance_from_centroid[len(stringer_top_distance_from_centroid) -1],
    #area_top_stringer) + q_t_1256 + q_s_s0_1256 - q_t_2345 - q_s_s0_2345 + q_t_2345 + q_s_s0_2345)

    return q_max_top_flange_value / t_12, q_max_bottom_flange_value / t_12, max(
        q_tot_front_spar, q_tot_middle_spar) * t_61
def drag_distribution(y, length_step, density, velocity):
    return load_factor * (drag_induced_function(y) + cd_0) * 0.5 * density * (
        velocity**2) * aerodynamic_data.chord_function(y)
def pitching_moment_function(y, density, velocity, length_step):
    # 0.5 rho V^2 S c
    # print(aerodynamic_data.moment_coef_function_10(y))
    return load_factor * moment_coef_function(y) * 0.5 * density * (velocity ** 2) * aerodynamic_data.chord_function(y) * \
           aerodynamic_data.chord_function(y)
    from Integrator import Integration

database_connector = DatabaseConnector()

# Import basic geometry
wing_span = database_connector.load_value("wing_span") / 2
outer_diameter = database_connector.load_value("df,outer")
radius_fuselage = outer_diameter / 2
surface_area = database_connector.load_value("surface_area") / 2
root_chord = database_connector.load_value("root_chord")
tip_chord = database_connector.load_value("tip_chord")
taper_ratio = database_connector.load_value("taper_ratio")
spanwise_location_engine = database_connector.load_value(
    "engine_spanwise_location")

chord_at_engine_location = aerodynamic_data.chord_function(
    spanwise_location_engine)
radius_engine = database_connector.load_value("d_engine") / 2

moment_arm_engine = (
    0.25 + 0.2) * aerodynamic_data.chord_function(spanwise_location_engine)
moment_arm_thrust = 1.5 * radius_engine

global_length_step = 0.1  # [m]

# Define the flight conditions
test_velocity = 236.32  # m/s
test_density = 1.225  # kg/m^2
lift_coef_function = aerodynamic_data.lift_coef_function_10
drag_induced_function = aerodynamic_data.drag_induced_function_10
moment_coef_function = aerodynamic_data.moment_coef_function_10
def lift_distribution(y, length_step, density, velocity):
    return load_factor * lift_coef_function(y) * 0.5 * density * (
        velocity**2) * aerodynamic_data.chord_function(y)
Example #7
0
def main_shear_stress(b):
    #basics

    list_coordinates = [(0.15, 0.06588533), (0.6, 0.0627513),
                        (0.6, -0.02702924), (0.15, -0.04083288)]

    AC = AC_lenght(b)
    lenghts = get_lenghts(list_coordinates)
    slopes = get_slopes(list_coordinates)
    Am = 0.5 * abs(
        sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in area_segments(
            [x * aerodynamic_data.chord_function(b)
             for x in list_coordinates])))

    #******************************************************
    if b <= 10:
        topstr = database_connector.load_wingbox_value(
            "top_number_of_stringers_1")  #number of top stringers
        botstr = database_connector.load_wingbox_value(
            "bottom_number_of_stringers_1")  #number of bottom stingers
    if 10 < b <= 20:
        topstr = database_connector.load_wingbox_value(
            "top_number_of_stringers_2")  #number of top stringers
        botstr = database_connector.load_wingbox_value(
            "bottom_number_of_stringers_2")  #number of bottom stingers
    if b > 20:
        topstr = database_connector.load_wingbox_value(
            "top_number_of_stringers_3")  #number of top stringers
        botstr = database_connector.load_wingbox_value(
            "bottom_number_of_stringers_3")  #number of bottom stingers
    A1 = database_connector.load_wingbox_value(
        "top_stringer_area")  #area of corner stringers
    A2 = database_connector.load_wingbox_value(
        "top_stringer_area")  #area of normal stringers
    t_spar = database_connector.load_wingbox_value("spar_thickness")
    t_skin = database_connector.load_wingbox_value("plate_thickness")

    distances_btwn_stringers = distances(topstr, botstr, lenghts)

    z_list = z(get_centroid(b), list_coordinates, topstr, botstr, lenghts,
               slopes, distances_btwn_stringers, AC)
    x_list = x(get_centroid(b), list_coordinates, topstr, botstr, lenghts,
               slopes, distances_btwn_stringers, AC)

    area_list = area_append(A1, A2, topstr, botstr)

    # print(area_list)
    # print(x_list)
    # print(z_list)

    #****** shear*****
    qb_list = delta_q_and_qb(z_list, x_list, area_list, b, x_shear(b),
                             z_shear(b))
    #print(qb_list)
    q_so = qso(list_coordinates, qb_list, slopes, get_centroid(b), AC, b, Am,
               x_shear(b), z_shear(b), lenghts, botstr)
    #print(q_so)
    q_t = qt(torsion(b), Am)
    #print(q_t)
    q_list = shear_flow(qb_list, q_t, q_so)

    thicc_list = []
    for i in range(botstr - 1):
        thicc_list.append(t_skin)
    thicc_list.append(t_spar)
    for i in range(topstr - 1):
        thicc_list.append(t_skin)
    thicc_list.append(t_spar)

    #print(thicc_list)
    shear_stress = [i / j for i, j in zip(q_list, thicc_list)]

    #max values
    # max bottom
    bottom_shear_list = []
    for i in range(botstr - 1):
        a = shear_stress[i]
        bottom_shear_list.append(a)
    # spars
    spar_shear_stress_list = [shear_stress[botstr - 1], shear_stress[-1]]
    top_plate_list = shear_stress[botstr:-1]

    bottom_shear_list_abs = [abs(x) for x in bottom_shear_list]
    spar_shear_stress_list_abs = [abs(x) for x in spar_shear_stress_list]
    top_plate_list_abs = [abs(x) for x in top_plate_list]

    max_tau_bottom_plate = max(bottom_shear_list_abs)
    max_tau_top_plate = max(top_plate_list_abs)
    max_tau_spars = max(spar_shear_stress_list_abs)

    max_list = [max_tau_bottom_plate, max_tau_top_plate,
                max_tau_spars]  #<---------------------------
    #print(q_list)
    #shear_stress_max = max(shear_stress)

    return max_list  #shear_stress #_max
def get_polar_moment_of_inertia(spanwise_location):
    """
    Calculates the polar moment of inertia of the wingbox around the centroid.
    It uses a combination of rect subdivision and boom approximation to find this moment.

    :param spanwise_location: The location of the cross-section along the span for which the polar moment of Inertia is calculated.
    :return: The polar moment of Inertia of the wingbox cross-section in m4
    """

    # Local coord system: x from LE to TE, y upwards

    centroid = get_centroid(spanwise_location)

    top_stringer_area = database_connector.load_wingbox_value(
        'top_stringer_area')
    bottom_stringer_area = database_connector.load_wingbox_value(
        'bottom_stringer_area')

    wingbox_corner_points = database_connector.load_wingbox_value(
        'wingbox_corner_points')

    def get_location(end_points):
        # Input end_points as [[x1,y1], [x2,y2]]
        return [(end_points[0][0] + end_points[1][0]) / 2 - centroid[0],
                (end_points[0][1] + end_points[1][1]) / 2 - centroid[1]]

    def get_length(end_points):
        # Input end_points as [[x1,y1], [x2,y2]]
        return ((end_points[0][0] - end_points[1][0])**2 +
                (end_points[0][1] - end_points[1][1])**2)**0.5

    # Get all plate dimensions by rearranging corner points
    leading_spar_chord = [[
        wingbox_corner_points[0][0], wingbox_corner_points[0][1]
    ], [wingbox_corner_points[3][0], wingbox_corner_points[3][1]]]
    trailing_spar_chord = [[
        wingbox_corner_points[1][0], wingbox_corner_points[1][1]
    ], [wingbox_corner_points[2][0], wingbox_corner_points[2][1]]]
    middle_spar_chord = [
        [(wingbox_corner_points[0][0] + wingbox_corner_points[1][0]) / 2,
         (wingbox_corner_points[0][1] + wingbox_corner_points[1][1]) / 2],
        [(wingbox_corner_points[2][0] + wingbox_corner_points[3][0]) / 2,
         (wingbox_corner_points[2][1] + wingbox_corner_points[3][1]) / 2]
    ]
    leading_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in leading_spar_chord
    ]
    trailing_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in trailing_spar_chord
    ]
    middle_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in middle_spar_chord
    ]
    leading_spar_location = get_location(leading_spar)
    trailing_spar_location = get_location(trailing_spar)
    middle_spar_location = get_location(middle_spar)
    leading_spar_length = get_length(leading_spar)
    trailing_spar_length = get_length(trailing_spar)
    middle_spar_length = get_length(middle_spar)
    middle_spar_end = database_connector.load_wingbox_value('third_spar_end')
    spar_thickness = database_connector.load_wingbox_value('spar_thickness')

    top_plate_chord = [[
        wingbox_corner_points[0][0], wingbox_corner_points[0][1]
    ], [wingbox_corner_points[1][0], wingbox_corner_points[1][1]]]
    bottom_plate_chord = [[
        wingbox_corner_points[2][0], wingbox_corner_points[2][1]
    ], [wingbox_corner_points[3][0], wingbox_corner_points[3][1]]]
    top_plate = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in top_plate_chord
    ]
    bottom_plate = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in bottom_plate_chord
    ]
    top_plate_location = get_location(top_plate)
    bottom_plate_location = get_location(bottom_plate)
    top_plate_length = get_length(top_plate)
    bottom_plate_length = get_length(bottom_plate)
    plate_thickness = database_connector.load_wingbox_value('plate_thickness')

    # Get stringer locations along the top and bottom plate:
    stringer_top_locations = np.transpose([
        np.linspace(top_plate[0][0], top_plate[1][0],
                    get_amount_of_stringers(spanwise_location, True)),
        np.linspace(top_plate[0][1], top_plate[1][1],
                    get_amount_of_stringers(spanwise_location, True))
    ])
    stringer_bottom_locations = np.transpose([
        np.linspace(bottom_plate[0][0], bottom_plate[1][0],
                    get_amount_of_stringers(spanwise_location, False)),
        np.linspace(bottom_plate[0][1], bottom_plate[1][1],
                    get_amount_of_stringers(spanwise_location, False))
    ])

    def ll_axis_term(area, location):
        # parallel axis term
        return area * (location[0]**2 + location[1]**2)

    def p_moi_rect(height, width, location):
        # Standard formula and parallel axis term
        # return (width * height * (width ** 2 + height ** 2)) / 12 + ll_axis_term(width * height, location)
        return (width * height ** 3) / 12 + ll_axis_term(width * height, [location[0], 0]) + \
               (height * width ** 3) / 12 + ll_axis_term(width * height, [0, location[1]])

    def p_moi_point(area, location):
        # Treat as point area and neglect terms except for parallel axis term
        return ll_axis_term(area, [location[0], 0]) + ll_axis_term(
            area, [0, location[1]])

    polar_moment_of_inertia = 0

    # Due to plates
    polar_moment_of_inertia += p_moi_rect(leading_spar_length, spar_thickness,
                                          leading_spar_location)
    polar_moment_of_inertia += p_moi_rect(trailing_spar_length, spar_thickness,
                                          trailing_spar_location)
    polar_moment_of_inertia += p_moi_rect(plate_thickness, top_plate_length,
                                          top_plate_location)
    polar_moment_of_inertia += p_moi_rect(plate_thickness, bottom_plate_length,
                                          bottom_plate_location)

    if spanwise_location < middle_spar_end:
        polar_moment_of_inertia += p_moi_rect(middle_spar_length,
                                              spar_thickness,
                                              middle_spar_location)

    # Due to top stringers
    for stringer_location in stringer_top_locations:
        polar_moment_of_inertia += p_moi_point(top_stringer_area,
                                               stringer_location)

    # Due to bottom stringers
    for stringer_location in stringer_bottom_locations:
        polar_moment_of_inertia += p_moi_point(bottom_stringer_area,
                                               stringer_location)

    return polar_moment_of_inertia * 0.16
def get_torsional_constant(spanwise_location):
    # centroid = get_centroid(spanwise_location)

    wingbox_corner_points = database_connector.load_wingbox_value(
        'wingbox_corner_points')

    def get_length(end_points):
        # Input end_points as [[x1,y1], [x2,y2]]
        return ((end_points[0][0] - end_points[1][0])**2 +
                (end_points[0][1] - end_points[1][1])**2)**0.5

    # Get all plate dimensions by rearranging corner points
    leading_spar_chord = [[
        wingbox_corner_points[0][0], wingbox_corner_points[0][1]
    ], [wingbox_corner_points[3][0], wingbox_corner_points[3][1]]]
    trailing_spar_chord = [[
        wingbox_corner_points[1][0], wingbox_corner_points[1][1]
    ], [wingbox_corner_points[2][0], wingbox_corner_points[2][1]]]
    middle_spar_chord = [
        [(wingbox_corner_points[0][0] + wingbox_corner_points[1][0]) / 2,
         (wingbox_corner_points[0][1] + wingbox_corner_points[1][1]) / 2],
        [(wingbox_corner_points[2][0] + wingbox_corner_points[3][0]) / 2,
         (wingbox_corner_points[2][1] + wingbox_corner_points[3][1]) / 2]
    ]
    leading_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in leading_spar_chord
    ]
    trailing_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in trailing_spar_chord
    ]
    middle_spar = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in middle_spar_chord
    ]
    leading_spar_length = get_length(leading_spar)
    trailing_spar_length = get_length(trailing_spar)
    spar_thickness = database_connector.load_wingbox_value('spar_thickness')

    top_plate_chord = [[
        wingbox_corner_points[0][0], wingbox_corner_points[0][1]
    ], [wingbox_corner_points[1][0], wingbox_corner_points[1][1]]]
    bottom_plate_chord = [[
        wingbox_corner_points[2][0], wingbox_corner_points[2][1]
    ], [wingbox_corner_points[3][0], wingbox_corner_points[3][1]]]
    top_plate = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in top_plate_chord
    ]
    bottom_plate = [
        x * aerodynamic_data.chord_function(spanwise_location)
        for x in bottom_plate_chord
    ]
    top_plate_length = get_length(top_plate)
    bottom_plate_length = get_length(bottom_plate)
    plate_thickness = database_connector.load_wingbox_value('plate_thickness')

    def area_segments(p):
        return zip(p, p[1:] + [p[0]])

    enclosed_area = 0.5 * abs(
        sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in area_segments([
            x * aerodynamic_data.chord_function(spanwise_location)
            for x in wingbox_corner_points
        ])))
    integral_equivalent = top_plate_length / plate_thickness + bottom_plate_length / plate_thickness + leading_spar_length / spar_thickness + \
                          trailing_spar_length / spar_thickness

    return (4 * enclosed_area**2) / integral_equivalent
Example #10
0
def torque_shear_flow(AC, Torsion, b, list_coordinates):

    Am = 0.5 * abs(
        sum(x0 * y1 - x1 * y0 for ((x0, y0), (x1, y1)) in area_segments(
            [x * aerodynamic_data.chord_function(b)
             for x in list_coordinates])))

    if b <= 10:
        three_spars = True
    else:
        three_spars = False

    if three_spars == True:

        try:
            with open("./data.pickle", 'rb') as file:
                data = pickle.load(file)
        except FileNotFoundError:
            with open("../InertialLoadingCalculator/data.pickle",
                      'rb') as file:
                data = pickle.load(file)
        y_span_lst = data[0]

        # TORQUE
        spanwise_location = b
        torsion_lst = data[7]
        torsion = sp.interpolate.interp1d(y_span_lst,
                                          torsion_lst,
                                          kind="cubic",
                                          fill_value="extrapolate")
        torque_y = torsion(spanwise_location)

        wingbox_points = database_connector.load_wingbox_value(
            "wingbox_points")
        G = database_connector.load_wingbox_value("shear_modulus_pa")
        chord_length = aerodynamic_data.chord_function(spanwise_location)
        centroid = get_centroid(spanwise_location)

        distances_1 = (wingbox_points[0][0] - centroid[0],
                       wingbox_points[0][1] - centroid[1])
        distances_2 = (wingbox_points[1][0] - centroid[0],
                       wingbox_points[1][1] - centroid[1])
        distances_3 = (wingbox_points[2][0] - centroid[0],
                       wingbox_points[2][1] - centroid[1])
        distances_4 = (wingbox_points[3][0] - centroid[0],
                       wingbox_points[3][1] - centroid[1])
        distances_5 = (wingbox_points[4][0] - centroid[0],
                       wingbox_points[4][1] - centroid[1])
        distances_6 = (wingbox_points[5][0] - centroid[0],
                       wingbox_points[5][1] - centroid[1])

        length_12 = abs(distances_1[0] - distances_2[0]) * chord_length
        length_23 = abs(distances_2[0] - distances_3[0]) * chord_length
        length_34 = abs(distances_3[1] - distances_4[1]) * chord_length
        length_61 = abs(distances_6[1] - distances_1[1]) * chord_length
        length_25 = abs(distances_2[1] - distances_5[1]) * chord_length

        t_12 = t_23 = t_45 = t_56 = database_connector.load_wingbox_value(
            "plate_thickness")
        t_34 = t_61 = t_25 = database_connector.load_wingbox_value(
            "spar_thickness")

        encl_area_1256 = (length_25 + length_61) * length_12 / 2
        encl_area_2345 = (length_25 + length_34) * length_23 / 2

        # Matrix
        matrix = np.array([[2 * encl_area_1256, 2 * encl_area_2345, 0],
                           [
                               1 / (2 * encl_area_1256 * G) *
                               (1 / t_12 + 1 / t_61 + 1 / t_25 + 1 / t_56),
                               1 / (2 * encl_area_1256 * G) * (-1 / t_25), -1
                           ],
                           [
                               1 / (2 * encl_area_2345 * G) * (-1 / t_25),
                               1 / (2 * encl_area_2345 * G) *
                               (1 / t_23 + 1 / t_34 + 1 / t_45 + 1 / t_25), -1
                           ]])

        # SHEAR DUE TO TORQUE
        solution_vector_t = np.array([torque_y, 0, 0])
        q_t_1256, q_t_2345, dtheta_t = np.linalg.solve(matrix,
                                                       solution_vector_t)

        q_t = (q_t_1256, q_t_2345)

    else:
        q_t_a = Torsion / 2 * Am
        q_t = (q_t_a, q_t_a)

    return q_t
def get_centroid(spanwise_location, verbose=False):
    """
    Calculates the X and Z component of the centroid.

    :param spanwise_location: The location of the cross-section along the span for which the centroid is calculated
    :param verbose: Print values while calculating
    :return: The centroid of the cross-section as a list of [X, Z]
    """
    chord_length = aerodynamic_data.chord_function(spanwise_location)

    # wing box configuration
    wingbox_corner_points = database_connector.load_wingbox_value(
        "wingbox_corner_points")
    left_top_corner_wingbox = wingbox_corner_points[0] * chord_length
    left_bottom_corner_wingbox = wingbox_corner_points[3] * chord_length
    right_top_corner_wingbox = wingbox_corner_points[1] * chord_length
    right_bottom_corner_wingbox = wingbox_corner_points[2] * chord_length

    length_top_plate = (math.sqrt(
        (right_top_corner_wingbox[0] - left_top_corner_wingbox[0])**2 +
        (left_top_corner_wingbox[1] - right_top_corner_wingbox[1])**2))
    height_front_spar = (left_top_corner_wingbox[1] -
                         left_bottom_corner_wingbox[1])
    height_back_spar = (right_top_corner_wingbox[1] -
                        right_bottom_corner_wingbox[1])
    length_bottom_plate = (math.sqrt(
        (right_top_corner_wingbox[0] - left_top_corner_wingbox[0])**2 +
        (-left_bottom_corner_wingbox[1] + right_bottom_corner_wingbox[1])**2))
    height_middle_spar = height_front_spar - math.sqrt(
        (length_bottom_plate / 2)**2 - (length_top_plate / 2)**2)
    # area_wingbox = length_top_plate * height_front_spar - (length_top_plate * (height_front_spar - height_back_spar))/2

    plate_thickness = database_connector.load_wingbox_value("plate_thickness")
    spar_thickness = database_connector.load_wingbox_value("spar_thickness")

    area_front_spar = spar_thickness * height_front_spar
    area_back_spar = spar_thickness * height_back_spar
    area_middle_spar = spar_thickness * height_middle_spar
    area_top_plate = plate_thickness * length_top_plate
    area_bottom_plate = plate_thickness * length_bottom_plate

    x_top_bottom_plate = (left_top_corner_wingbox[0] +
                          right_top_corner_wingbox[0]) * 1 / 2
    x_front_spar = left_top_corner_wingbox[0]
    x_back_spar = right_top_corner_wingbox[0]
    x_middle_spar = (
        left_top_corner_wingbox[0] +
        (right_top_corner_wingbox[0] - left_top_corner_wingbox[0]) / 2)

    z_top_plate = (left_top_corner_wingbox[1] +
                   right_top_corner_wingbox[1]) * 1 / 2
    z_bottom_plate = (left_bottom_corner_wingbox[1] +
                      right_bottom_corner_wingbox[1]) * 1 / 2
    z_front_spar = (left_top_corner_wingbox[1] +
                    left_bottom_corner_wingbox[1]) * 1 / 2
    z_middle_spar = height_middle_spar / 2 + z_bottom_plate
    z_back_spar = (right_top_corner_wingbox[1] +
                   right_bottom_corner_wingbox[1]) * 1 / 2

    # Reinforcements: stringers
    area_top_stringer = database_connector.load_wingbox_value(
        "top_stringer_area")
    area_bottom_stringer = database_connector.load_wingbox_value(
        "bottom_stringer_area")

    def get_x_coordinates_stringer(spanwise_location):
        # get x-coordinates stringers
        x_coordinates_stringers_top = []
        x_coordinates_stringers_bottom = []
        number_stringers_top = get_amount_of_stringers(spanwise_location,
                                                       "top")
        number_stringers_bottom = get_amount_of_stringers(
            spanwise_location, "bottom")

        spacing_stringers_top = length_top_plate / (number_stringers_top + 1)
        spacing_stringers_bottom = length_bottom_plate / (
            number_stringers_bottom + 1)

        for number_stringer in range(1, number_stringers_top + 1):
            x_coordinate_current_stringer = left_top_corner_wingbox[
                0] + number_stringer * spacing_stringers_top
            x_coordinates_stringers_top.append(x_coordinate_current_stringer)
            # print(number_stringer)
        for number_stringer in range(1, number_stringers_bottom + 1):
            x_coordinate_current_stringer = left_bottom_corner_wingbox[
                0] + number_stringer * spacing_stringers_bottom
            x_coordinates_stringers_bottom.append(
                x_coordinate_current_stringer)
            # print(number_stringer)
        return x_coordinates_stringers_top, x_coordinates_stringers_bottom

    def get_z_coordinates_stringer(spanwise_location):
        z_coordinates_stringers_top = []
        z_coordinates_stringers_bottom = []

        number_stringers_top = get_amount_of_stringers(spanwise_location,
                                                       "top")
        number_stringers_bottom = get_amount_of_stringers(
            spanwise_location, "bottom")

        spacing_stringers_top = length_top_plate / (number_stringers_top + 1)
        spacing_stringers_bottom = length_bottom_plate / (
            number_stringers_bottom + 1)

        #top
        sin_angle_top = (left_top_corner_wingbox[1] -
                         right_top_corner_wingbox[1]) / (length_top_plate)

        for number_stringer in range(1, number_stringers_top + 1):
            z_coordinate_current_top_stringer = left_top_corner_wingbox[
                1] - number_stringer * sin_angle_top * spacing_stringers_top
            z_coordinates_stringers_top.append(
                z_coordinate_current_top_stringer)
        #bottom
        sin_angle_bottom = (-left_bottom_corner_wingbox[1] -
                            right_top_corner_wingbox[1]) / length_bottom_plate
        for number_stringer in range(1, number_stringers_bottom + 1):
            z_coordinate_current_bottom_stringer = left_bottom_corner_wingbox[
                1] - number_stringer * sin_angle_bottom * spacing_stringers_bottom
            z_coordinates_stringers_bottom.append(
                z_coordinate_current_bottom_stringer)

        # #z axis points up
        # print(z_coordinates_stringers_top)
        # print(z_coordinates_stringers_bottom)
        return z_coordinates_stringers_top, z_coordinates_stringers_bottom

    def calculate_x_coordinate_centroid(x_lst, area_lst):
        AX_lst = []
        for index in range(len(x_lst)):
            AX_lst.append(x_lst[index] * area_lst[index])
            # print(index)

        sum_area = sum(area_lst)
        sum_AX = sum(AX_lst)
        return sum_AX / sum_area

    def calculate_z_coordinate_centroid(z_lst, area_lst):
        AZ_lst = []
        for element in range(len(z_lst)):
            AZ_lst.append(z_lst[element] * area_lst[element])
        sum_area = sum(area_lst)
        sum_AZ = sum(AZ_lst)
        return sum_AZ / sum_area

    def calculate_Ixz(x_lst, z_lst, area_lst):
        IXZ_AXZ_lst = []
        for element in range(len(x_lst)):
            #print(z_lst[element])
            IXZ_AXZ_lst.append(x_lst[element] * z_lst[element] *
                               area_lst[element])
            #print(element)
        I_XZ = sum(IXZ_AXZ_lst)
        return I_XZ

    area_lst = [
        area_top_plate, area_bottom_plate, area_front_spar, area_middle_spar,
        area_back_spar
    ]
    x_coordinates_lst = [
        x_top_bottom_plate, x_top_bottom_plate, x_front_spar, x_middle_spar,
        x_back_spar
    ]
    z_coordinates_lst = [
        z_top_plate, z_bottom_plate, z_front_spar, z_middle_spar, z_back_spar
    ]

    # coordinates centroid without ribs and stringers (wrt LE-chord intersection)
    x_centroid_no_reinforcements = calculate_x_coordinate_centroid(
        x_coordinates_lst[0:5], area_lst[0:5])
    z_centroid_no_reinforcements = calculate_z_coordinate_centroid(
        z_coordinates_lst[0:5], area_lst[0:5])
    if verbose:
        print(
            "\nThe centroid w.r.t. the LE-chord without any ribs or stringers equals [x,z]: "
        )
        print([x_centroid_no_reinforcements, z_centroid_no_reinforcements])

    # coordinates centroid with only stringers
    x_coordinates_stringers_top, x_coordinates_stringers_bottom = get_x_coordinates_stringer(
        spanwise_location)
    z_coordinates_stringers_top, z_coordinates_stringers_bottom = get_z_coordinates_stringer(
        spanwise_location)
    x_coordinates_lst = x_coordinates_lst + x_coordinates_stringers_top + x_coordinates_stringers_bottom
    z_coordinates_lst = z_coordinates_lst + z_coordinates_stringers_top + z_coordinates_stringers_bottom
    for add_area in range(len(x_coordinates_stringers_top)):
        area_lst.append(area_top_stringer)
    for add_area in range(len(x_coordinates_stringers_bottom)):
        area_lst.append(area_bottom_stringer)
    x_centroid_stringers_only = calculate_x_coordinate_centroid(
        x_coordinates_lst, area_lst)
    z_centroid_stringers_only = calculate_z_coordinate_centroid(
        z_coordinates_lst, area_lst)
    if verbose:
        print("\nThe centroid w.r.t. the LE-chord with stringers [x,z]: ")
        print([x_centroid_stringers_only, z_centroid_stringers_only])
        # print(x_coordinates_lst)
        # print(len(x_coordinates_lst))
        # print(z_coordinates_lst)
        # print(len(z_coordinates_lst))
        # print(len(area_lst))
    return [x_centroid_stringers_only, z_centroid_stringers_only]
    I_XZ = calculate_Ixz(x_coordinates_lst, z_coordinates_lst, area_lst)

    return [x_centroid_stringers_only, z_centroid_stringers_only, I_XZ]