예제 #1
0
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
예제 #2
0
def add_controls(axes_2d, axes_3d, aircraft):
    """
    Add control surfaces 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 (_, _, control), (_, _, wing) in ot.all_controls(aircraft):
        # ----- Add outer control geometry -----
        color = C.CONTROL_FLAP if control.device_type == 'flap' else C.CONTROL_SLAT
        vertex_order = 'dabc' if control.device_type == 'flap' else 'bcda'
        points = np.array([
            control.abs_vertices[vertex_name] for vertex_name in vertex_order
        ])
        _plot_XYZ_points(axes_2d,
                         axes_3d,
                         points,
                         wing.symmetry,
                         linewidth=PS.LINEWIDTH_c,
                         color=color)

        # ----- Add hinges -----
        points = np.array([
            control.abs_hinge_vertices['p_inner'],
            control.abs_hinge_vertices['p_outer'],
        ])
        _plot_XYZ_points(axes_2d,
                         axes_3d,
                         points,
                         wing.symmetry,
                         linewidth=PS.LINEWIDTH_c,
                         color=C.CONTROL_HINGE)
예제 #3
0
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)
예제 #4
0
def get_aircraft_controls(aircraft, wing_uid, idx_wing, tixi, tigl):
    """
    Extract the controls surfaces

    Args:
        :aircraft: Aircraft model
        :wing_uid: Name of the wing
        :idx_wing: Index of the wing
        :tixi: Tixi handle
        :tigl: Tigl handle

    .. warning::

        * CPACS3 changed the control surface defintions!
        * In Tigl 3.0.0 some fuctions for controlSurfaces are missing
          (currently we use a workaround, see PATCH_* functions)
        * In CPACS3 relative coordinates can be defined based on a 'section' or
          'componentSegment', currently we assume the old definition (based on
          'componentSegment')
    """

    # Abbreviate long function name
    tigl.get_eta_xsi = tigl.wingComponentSegmentPointGetSegmentEtaXsi

    # ---------- Iterate through component sections (contain control surfaces) ----------
    num_comp_sections = tigl.wingGetComponentSegmentCount(idx_wing)
    for idx_comp_section in range(1, num_comp_sections + 1):
        name_comp_section = tigl.wingGetComponentSegmentUID(
            idx_wing, idx_comp_section)

        # ---------- Iterate through controls ----------
        # PATCHED # for idx_control in range(1, tigl.getControlSurfaceCount(name_comp_section) + 1):
        num_controls = PATCH_getControlSurfaceCount(tixi, name_comp_section)
        for idx_control in range(1, num_controls + 1):
            for device_pos in ('leading', 'trailing'):
                # PATCHED # control_uid = tigl.getControlSurfaceUID(name_comp_section, idx_control)
                control_uid = PATCH_getControlSurfaceUID(
                    tixi, name_comp_section, idx_control)
                logger.debug(
                    f"Wing {idx_wing:d} has control '{control_uid:s}'")
                node_control = XPATHS.CONTROL(idx_wing, idx_comp_section,
                                              idx_control, device_pos)

                # Try to read the relative coordinates for each control (eta, xsi)
                # ======================================================
                # TODO: does tixi.getDoubleElement() raise an error???
                # ======================================================
                try:
                    # Control vertices
                    etaLE_ib = tixi.getDoubleElement(
                        node_control + "/outerShape/innerBorder/etaLE/eta")
                    etaTE_ib = tixi.getDoubleElement(
                        node_control + "/outerShape/innerBorder/etaTE/eta")
                    xsiLE_ib = tixi.getDoubleElement(
                        node_control + "/outerShape/innerBorder/xsiLE/xsi")
                    etaLE_ob = tixi.getDoubleElement(
                        node_control + "/outerShape/outerBorder/etaLE/eta")
                    etaTE_ob = tixi.getDoubleElement(
                        node_control + "/outerShape/outerBorder/etaTE/eta")
                    xsiLE_ob = tixi.getDoubleElement(
                        node_control + "/outerShape/outerBorder/xsiLE/xsi")

                    # Hinge parameters
                    hingeXsi_ib = tixi.getDoubleElement(
                        node_control + "/path/innerHingePoint/hingeXsi")
                    hingeXsi_ob = tixi.getDoubleElement(
                        node_control + "/path/outerHingePoint/hingeXsi")

                except tixiwrapper.TixiException:
                    logger.debug(
                        f"No control data found for NODE {node_control:s}")
                    continue

                if device_pos == 'leading':
                    # Enforcing parallelism between control edges and x-axis
                    xsiLE_ib = 0.0
                    xsiLE_ob = 0.0

                    # Relative coordinates of control w.r.t. component segment
                    _, segment_uid_inner, eta_inner, xsi_inner = tigl.get_eta_xsi(
                        name_comp_section, etaTE_ib, xsiTE_ib)
                    _, segment_uid_outer, eta_outer, xsi_outer = tigl.get_eta_xsi(
                        name_comp_section, etaTE_ob, xsiTE_ob)

                    # Relative coordinates of control hinge line w.r.t. component segment
                    _, _, _, xsi_h1 = tigl.get_eta_xsi(name_comp_section,
                                                       etaTE_ib, hingeXsi_ib)
                    _, _, _, xsi_h2 = tigl.get_eta_xsi(name_comp_section,
                                                       etaTE_ob, hingeXsi_ob)

                elif device_pos == 'trailing':
                    xsiTE_ib = 1.0
                    xsiTE_ob = 1.0

                    # Relative coordinates of control w.r.t. component segment
                    _, segment_uid_inner, eta_inner, xsi_inner = tigl.get_eta_xsi(
                        name_comp_section, etaLE_ib, xsiLE_ib)
                    _, segment_uid_outer, eta_outer, xsi_outer = tigl.get_eta_xsi(
                        name_comp_section, etaLE_ob, xsiLE_ob)

                    # Relative coordinates of control hinge line w.r.t. component segment
                    _, _, _, xsi_h1 = tigl.get_eta_xsi(name_comp_section,
                                                       etaLE_ib, hingeXsi_ib)
                    _, _, _, xsi_h2 = tigl.get_eta_xsi(name_comp_section,
                                                       etaLE_ob, hingeXsi_ob)

                # ADD WING CONTROL AND SET ATTRIBUTES
                control = aircraft.wings[wing_uid].add_control(control_uid)
                control.device_type = 'flap' if device_pos == 'trailing' else 'slat'

                # Set DEFAULT deflection to 0
                control.deflection = 0

                control.rel_vertices['eta_inner'] = eta_inner
                control.rel_vertices['xsi_inner'] = xsi_inner
                control.rel_vertices['eta_outer'] = eta_outer
                control.rel_vertices['xsi_outer'] = xsi_outer

                control.rel_hinge_vertices['xsi_inner'] = xsi_h1
                control.rel_hinge_vertices['xsi_outer'] = xsi_h2

                control.segment_uid['inner'] = segment_uid_inner
                control.segment_uid['outer'] = segment_uid_outer

    # ----- CONTROL SURFACE DEFLECTION -----
    try:
        n_control_dev = tixi.getNamedChildrenCount(XPATHS.TOOLSPEC_CONTROL,
                                                   'controlDevice')
    except:
        n_control_dev = 0

    for idx_control in range(1, n_control_dev + 1):
        node_control_device = XPATHS.TOOLSPEC_CONTROL + '/controlDevice[{}]'.format(
            idx_control)
        control_uid = tixi.getTextAttribute(node_control_device, 'uID')
        deflection = 0
        deflection_mirror = None

        try:
            deflection = tixi.getDoubleElement(node_control_device +
                                               '/deflection')
        except tixiwrapper.TixiException:
            logger.error(
                "Unable to read 'deflection' for control '{:s}'".format(
                    control_uid))

        try:
            deflection_mirror = tixi.getDoubleElement(node_control_device +
                                                      '/deflectionMirror')
        except:
            logger.warning(
                "Unable to read 'deflection_mirror' for control '{:s}'".format(
                    control_uid))

        deflection_is_set = False

        for this_wing in all_wings(aircraft):
            wing = this_wing[2]

            if control_uid in wing.controls.keys():
                wing.controls[control_uid].deflection = deflection
                wing.controls[
                    control_uid].deflection_mirror = deflection_mirror
                deflection_is_set = True
                break

        if not deflection_is_set:
            logger.error("Could not set deflection for control '{:s}'".format(
                control_uid))
            raise ComponentDefinitionError(
                "Control '{:s}' not found".format(control_uid))

    # ----- CONTROL CHECKS -----
    for this_control, _ in all_controls(aircraft):
        this_control[2].check()