def add_wings(axes_2d, axes_3d, aircraft): """ Add wings (segment vertices) to axes objects Args: :axes_2d: 2D axes object (matplotlib) :axes_3d: 3D axes object (matplotlib) :aircraft: (object) data structure for aircraft model """ axes_yz, axes_xz, axes_xy = axes_2d for (_, _, segment), (_, _, wing) in ot.all_segments(aircraft): points = np.array([ segment.vertices['a'], segment.vertices['b'], segment.vertices['c'], segment.vertices['d'], segment.vertices['a'], ]) _plot_XYZ_points(axes_2d, axes_3d, points, wing.symmetry, linewidth=PS.LINEWIDTH_b, color=C.MESH_MIRROR)
def set_autopanels(aircraft, settings): """ Automatically set chord- and spanwise discretisation settings Args: :aircraft: (object) data structure for aircraft geometry :autopanels_c: (int) number of chordwise panels on the main wing :autopanels_s: (int) number of spanwise panels on the main wing """ autopanels_c = settings.settings.get('vlm_autopanels_c', MIN_AUTOPANELS) autopanels_s = settings.settings.get('vlm_autopanels_s', MIN_AUTOPANELS) for this_segment, _ in ot.all_segments(aircraft): segment = this_segment[2] if segment.panels['num_c'] is None: segment.panels['num_c'] = autopanels_c if segment.panels['num_s'] is None: wing_span = segment.parent_wing.span segment_span = segment.geometry['span'] segment.panels['num_s'] = ceil((segment_span/wing_span)*autopanels_s) for this_control, this_wing in ot.all_controls(aircraft): control = this_control[2] if control.panels['num_c'] is None: control.panels['num_c'] = autopanels_c
def _scale_plots(axes_2d, axes_3d, aircraft): """ Correct the axes scaling Args: :axes_2d: 2D axes object (matplotlib) :axes_3d: 3D axes object (matplotlib) :aircraft: Aircraft model """ axes_yz, axes_xz, axes_xy = axes_2d # Iterate through segment vertices to determine required plot dimension lims = np.zeros((2, 3)) for (_, _, segment), (_, _, wing) in ot.all_segments(aircraft): points = np.array([ segment.vertices['a'], segment.vertices['b'], segment.vertices['c'], segment.vertices['d'], segment.vertices['a'] ]) _get_limits(points, lims, symmetry=wing.symmetry) # Adjust scaling for all axes objects _scale_fig(axes_3d, lims) _scale_fig(axes_yz, lims, directions='yz') _scale_fig(axes_xz, lims, directions='xz') _scale_fig(axes_xy, lims, directions='xy')
def pre_panelling(aircraft): """ Create subdivisions and subareas for all aircraft wings Note: * This routine divides the wing into subdivisions and subareas in order to generate a suitable mesh for wing with control surfaces. * In a first step "mandatory" subdivisions are made: The wing is divided into a minimum amount of subareas according to the leading and trailing edge control surfaces. * In a second step further spanwise subdivisions are added. Args: :aircraft: (obj) aircraft object """ # TODO: # - Potential problem: # * The algorithm is based on "correct ordering" of segments: # Segments must be ordered from root to tip (check if this always given!?) # ===== PART ONE (MANDATORY SUBDIVISIONS) ===== # For each control we must add suitable subdivisions for this_control, this_wing in ot.all_controls(aircraft): control = this_control[2] wing = this_wing[2] # Segment names on which control surface edges are located segment_inner_name = control.segment_uid['inner'] segment_outer_name = control.segment_uid['outer'] # Control surface geometry eta_inner = control.rel_vertices['eta_inner'] eta_outer = control.rel_vertices['eta_outer'] xsi_inner = control.rel_vertices['xsi_inner'] xsi_outer = control.rel_vertices['xsi_outer'] # Hinge axis xsi_h1 = control.rel_hinge_vertices['xsi_inner'] xsi_h2 = control.rel_hinge_vertices['xsi_outer'] # ----- CASE (A) ----- # The left and right edge of the control are located on SAME segment if segment_inner_name == segment_outer_name: wing.segments[segment_inner_name].add_subdivision_for_control( eta_inner, eta_outer, control, xsi_inner, xsi_outer, xsi_h1, xsi_h2) # ----- CASE (B) ----- # - The control surface spans over one or more segment borders # - Now we will make a list of segments over which the control spans # - We will interpolate the position of the control and the hinge # axis at segment borders else: # Create a list of segments which contain the control # list_of_segments[0]: segment_uid # list_of_segments[1]: eta_inner # list_of_segments[2]: eta_outer # list_of_segments[3]: xsi_inner # list_of_segments[4]: xsi_outer # list_of_segments[5]: xsi_h1 # list_of_segments[6]: xsi_h2 list_of_segments = [] # Flags to indicate that the inner or outer control positions have been set inner_set = False outer_set = False # To start with we use averaged values for xsi (geometry and hinge axis) xsi_avg = (xsi_inner + xsi_outer)/2 xsi_h_avg = (xsi_h1 + xsi_h2)/2 for segment_uid in wing.segments.keys(): if segment_uid == segment_inner_name: inner_set = True # Note: eta_outer = 1 list_of_segments.append([segment_uid, eta_inner, 1, xsi_inner, xsi_avg, xsi_h1, xsi_h_avg]) continue elif inner_set and not outer_set: # Note: eta_inner = 0 # Note: eta_outer = 1 list_of_segments.append([segment_uid, 0, 1, xsi_avg, xsi_avg, xsi_h_avg, xsi_h_avg]) # If we are on the last segment we must update some incorrectly set values if segment_uid == segment_outer_name: outer_set = True list_of_segments[-1][2] = eta_outer list_of_segments[-1][4] = xsi_outer list_of_segments[-1][6] = xsi_h2 break # Potentially, we must readjust the control surface geometry/hinge axis at borders if (xsi_inner != xsi_outer) or (xsi_h1 != xsi_h2): # Let's first compute the "length" of the control surface control_len = [0, ] for row in list_of_segments: segment_uid, eta_i, eta_o, xsi_i, xsi_o, xsi_hi, xsi_ho = row segment = wing.segments[segment_uid] segment_vertices = segment.vertices a = get_abs_segment_point_coords(segment_vertices, eta_i, xsi_i) b = get_abs_segment_point_coords(segment_vertices, eta_o, xsi_o) ab = b - a # l: total length of control l = control_len[-1] control_len.append(l + np.sqrt(np.dot(ab, ab))) l = control_len[-1] # Now, we update the xsi values using linear interpolation for i, row in enumerate(list_of_segments): segment_uid, eta_i, eta_o, xsi_i, xsi_o, xsi_hi, xsi_ho = row # Update the xsi values l_i = control_len[i] l_o = control_len[i+1] xsi_i = lin_interpol((xsi_inner, xsi_outer), (0, l), l_i) xsi_o = lin_interpol((xsi_inner, xsi_outer), (0, l), l_o) xsi_hi = lin_interpol((xsi_h1, xsi_h2), (0, l), l_i) xsi_ho = lin_interpol((xsi_h1, xsi_h2), (0, l), l_o) list_of_segments[i] = [segment_uid, eta_i, eta_o, xsi_i, xsi_o, xsi_hi, xsi_ho] # Finally, we create the subdivisions using our list for row in list_of_segments: segment_uid, eta_i, eta_o, xsi_i, xsi_o, xsi_h1, xsi_h2 = row wing.segments[segment_uid].add_subdivision_for_control( eta_i, eta_o, control, xsi_i, xsi_o, xsi_h1, xsi_h2) # ===== PART TWO (ADDITIONAL SPANWISE SUBDIVISIONS) ===== # - Adding additional spanwise subdivisions is done here in Python rather # than in the C code as it is more convenient to keep track of which # parts (subareas) of the discretised surface have which functions for this_segment, _ in ot.all_segments(aircraft): segment = this_segment[2] for eta in np.linspace(0, 1, segment.panels['num_s']+1): if (eta == 0) or (eta == 1): continue segment.add_subdivision(eta, eta, ignore_inval_eta=True)