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)
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
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]