Ejemplo n.º 1
0
def geometry_mesh(surface, comp=None):
    """
    OpenMDAO component that performs mesh manipulation functions. It reads in
    the initial mesh from the surface dictionary and outputs the altered
    mesh based on the geometric design variables.

    Parameters
    ----------
    sweep : float
        Shearing sweep angle in degrees.
    dihedral : float
        Dihedral angle in degrees.
    twist[ny] : numpy array
        1-D array of rotation angles for each wing slice in degrees.
    chord_dist[ny] : numpy array
        Chord length for each panel edge.
    taper : float
        Taper ratio for the wing; 1 is untapered, 0 goes to a point at the tip.
<<<<<<< HEAD
=======
    comp : (optional) OpenAeroStruct component object.
>>>>>>> 7eefd15e6c26c95cbbd9f303d23ecb4716c2fea3

    Returns
    -------
    mesh[nx, ny, 3] : numpy array
        Modified mesh based on the initial mesh in the surface dictionary and
        the geometric design variables.
    """
    if not comp:
        comp = GeometryMesh(surface)
    params = {}
    #
    # The following is copied from the __init__() method of GeometryMesh()
    #
    ny = surface['num_y']
    ones_list = ['taper', 'chord_cp']     # Variables that should be initialized to one
    zeros_list = ['sweep', 'dihedral', 'twist_cp', 'xshear_cp', 'zshear_cp']     # Variables that should be initialized to zero
    set_list = ['span']     # Variables that should be initialized to given value
    all_geo_vars = ones_list + zeros_list + set_list
    geo_params = {}
    for var in all_geo_vars:
        if len(var.split('_')) > 1:
            param = var.split('_')[0]
            if var in ones_list:
                val = np.ones(ny)
            elif var in zeros_list:
                val = np.zeros(ny)
            else:
                val = surface[var]
        else:
            param = var
            if var in ones_list:
                val = 1.0
            elif var in zeros_list:
                val = 0.0
            else:
                val = surface[var]
        geo_params[param] = val
Ejemplo n.º 2
0
    def setup_aero(self):
        """
        Specific method to add the necessary components to the problem for an
        aerodynamic problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'aero'

        # Create the base root-level group
        root = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']
            tmp_group = Group()

            # Add independent variables that do not belong to a specific component
            indep_vars = [('twist_cp', numpy.zeros(surface['num_twist'])),
                          ('dihedral', surface['dihedral']),
                          ('sweep', surface['sweep']),
                          ('span', surface['span']),
                          ('taper', surface['taper']),
                          ('disp', numpy.zeros((surface['num_y'], 6)))]

            # Obtain the Jacobian to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])

            # Add aero components to the surface-specific group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline('twist_cp', 'twist', jac_twist),
                          promotes=['*'])
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('def_mesh',
                          TransferDisplacements(surface),
                          promotes=['*'])
            tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*'])

            # Add tmp_group to the problem as the name of the surface.
            # Note that is a group and performance group for each
            # individual surface.
            name_orig = name.strip('_')
            name = name_orig
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=[])')

            # Add a performance group for each surface
            name = name_orig + '_perf'
            exec('root.add("' + name + '", ' + 'VLMFunctionals(surface)' +
                 ', promotes=["v", "alpha", "M", "Re", "rho"])')

        # Add problem information as an independent variables component
        prob_vars = [('v', self.prob_dict['v']),
                     ('alpha', self.prob_dict['alpha']),
                     ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']),
                     ('rho', self.prob_dict['rho'])]
        root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*'])

        # Add a single 'aero_states' component that solves for the circulations
        # and forces from all the surfaces.
        # While other components only depends on a single surface,
        # this component requires information from all surfaces because
        # each surface interacts with the others.
        root.add('aero_states',
                 VLMStates(self.surfaces, self.prob_dict),
                 promotes=['circulations', 'v', 'alpha', 'rho'])

        # Explicitly connect parameters from each surface's group and the common
        # 'aero_states' group.
        # This is necessary because the VLMStates component requires information
        # from each surface, but this information is stored within each
        # surface's group.
        for surface in self.surfaces:
            name = surface['name']

            # Perform the connections with the modified names within the
            # 'aero_states' group.
            root.connect(name[:-1] + '.def_mesh',
                         'aero_states.' + name + 'def_mesh')
            root.connect(name[:-1] + '.b_pts', 'aero_states.' + name + 'b_pts')
            root.connect(name[:-1] + '.c_pts', 'aero_states.' + name + 'c_pts')
            root.connect(name[:-1] + '.normals',
                         'aero_states.' + name + 'normals')

            # Connect the results from 'aero_states' to the performance groups
            root.connect('aero_states.' + name + 'sec_forces',
                         name + 'perf' + '.sec_forces')

            # Connect S_ref for performance calcs
            root.connect(name[:-1] + '.S_ref', name + 'perf' + '.S_ref')

        # Actually set up the problem
        self.setup_prob()
Ejemplo n.º 3
0
    def setup_struct(self):
        """
        Specific method to add the necessary components to the problem for a
        structural problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'struct'

        # Create the base root-level group
        root = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface.
            # This group's name is whatever the surface's name is.
            # The default is 'wing'.
            name = surface['name']
            tmp_group = Group()

            surface['r'] = surface['r'] / 5
            surface['t'] = surface['r'] / 20

            # Add independent variables that do not belong to a specific component.
            # Note that these are the only ones necessary for structual-only
            # analysis and optimization.
            indep_vars = [
                ('thickness_cp', numpy.ones(surface['num_thickness']) *
                 numpy.max(surface['t'])), ('r', surface['r']),
                ('loads', surface['loads'])
            ]

            # Obtain the Jacobians to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])
            jac_thickness = get_bspline_mtx(surface['num_thickness'],
                                            surface['num_y'] - 1)

            # Add structural components to the surface-specific group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline('twist_cp', 'twist', jac_twist),
                          promotes=['*'])
            tmp_group.add('thickness_bsp',
                          Bspline('thickness_cp', 'thickness', jac_thickness),
                          promotes=['*'])
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('tube', MaterialsTube(surface), promotes=['*'])
            tmp_group.add('struct_states',
                          SpatialBeamStates(surface),
                          promotes=['*'])
            tmp_group.add('struct_funcs',
                          SpatialBeamFunctionals(surface),
                          promotes=['*'])

            # Add tmp_group to the problem with the name of the surface.
            # The default is 'wing'.
            nm = name
            name = name[:-1]
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=[])')

        # Actually set up the problem
        self.setup_prob()
Ejemplo n.º 4
0
# Define the independent variables
indep_vars = [
    ('span', span),
    ('twist', numpy.zeros(num_y)),
    ('v', v),
    ('alpha', alpha),
    ('rho', rho),
    ('r', r),
    ('t', t),
]

indep_vars_comp = IndepVarComp(indep_vars)
tube_comp = MaterialsTube(num_y)

mesh_comp = GeometryMesh(mesh, aero_ind, num_twist)
spatialbeamstates_comp = SpatialBeamStates(num_y, E, G)
def_mesh_comp = TransferDisplacements(num_y)
vlmstates_comp = VLMStates(num_y)
loads_comp = TransferLoads(num_y)

vlmfuncs_comp = VLMFunctionals(num_y, CL0, CD0)
spatialbeamfuncs_comp = SpatialBeamFunctionals(num_y, E, G, stress, mrho)
fuelburn_comp = FunctionalBreguetRange(W0, CT, a, R, M)
eq_con_comp = FunctionalEquilibrium(W0)

root.add('indep_vars', indep_vars_comp, promotes=['*'])
root.add('tube', tube_comp, promotes=['*'])

# Add components to the MDA here
coupled = Group()
Ejemplo n.º 5
0
def geometry_mesh(surface, comp=None):
    """
    OpenMDAO component that performs mesh manipulation functions. It reads in
    the initial mesh from the surface dictionary and outputs the altered
    mesh based on the geometric design variables.

    Parameters
    ----------
    sweep : float
        Shearing sweep angle in degrees.
    dihedral : float
        Dihedral angle in degrees.
    twist[ny] : numpy array
        1-D array of rotation angles for each wing slice in degrees.
    chord_dist[ny] : numpy array
        Chord length for each panel edge.
    taper : float
        Taper ratio for the wing; 1 is untapered, 0 goes to a point at the tip.
    comp : (optional) OpenAeroStruct component object.

    Returns
    -------
    mesh[nx, ny, 3] : numpy array
        Modified mesh based on the initial mesh in the surface dictionary and
        the geometric design variables.
    """
    if not comp:
        comp = GeometryMesh(surface)
    params = {}
    #
    # The following is copied from the __init__() method of GeometryMesh()
    #
    ny = surface['num_y']
    ones_list = ['taper', 'chord_cp']     # Variables that should be initialized to one
    zeros_list = ['sweep', 'dihedral', 'twist_cp', 'xshear_cp', 'zshear_cp']     # Variables that should be initialized to zero
    set_list = ['span']     # Variables that should be initialized to given value
    all_geo_vars = ones_list + zeros_list + set_list
    geo_params = {}
    for var in all_geo_vars:
        if len(var.split('_')) > 1:
            param = var.split('_')[0]
            if var in ones_list:
                val = np.ones(ny)
            elif var in zeros_list:
                val = np.zeros(ny)
            else:
                val = surface[var]
        else:
            param = var
            if var in ones_list:
                val = 1.0
            elif var in zeros_list:
                val = 0.0
            else:
                val = surface[var]
        geo_params[param] = val
        if var in surface['geo_vars']:
            params.update({param: val})
    unknowns = {
        'mesh': comp.mesh
    }
    resids = None
    comp.solve_nonlinear(params, unknowns, resids)
    mesh = unknowns.get('mesh')
    return mesh
Ejemplo n.º 6
0
                      ('dihedral', 0.), ('sweep', 0.), ('taper', 1.0),
                      ('v', v), ('alpha', alpha), ('rho', rho), ('r', r),
                      ('thick', thick), ('zeta', zeta)]

        #######################
        # Calls of components #
        #######################
        root = om.Group()

        # Components before the time loop

        for name, val in indep_vars:
            root.set_input_defaults(name, val)
        root.add_subsystem('tube', MaterialsTube(n=num_y_sym), promotes=['*'])
        root.add_subsystem('mesh',
                           GeometryMesh(mesh=full_wing_mesh,
                                        num_twist=num_twist),
                           promotes=['*'])
        root.add_subsystem('matrices',
                           SpatialBeamMatrices(nx=num_x,
                                               n=num_y_sym,
                                               E=E,
                                               G=G,
                                               mrho=mrho,
                                               fem_origin=fem_origin),
                           promotes=['*'])
        SBEIG = SpatialBeamEIG(n=num_y_sym, num_dt=num_dt, final_t=final_t)
        root.add_subsystem('eig', SBEIG, promotes=['*'])

        # Time loop
        # coupled = om.Group()
        # for t in range(num_dt):
Ejemplo n.º 7
0
def setup(num_inboard=2, num_outboard=3, check=False, out_stream=sys.stdout):
    ''' Setup the aerostruct mesh using OpenMDAO'''

    # Define the aircraft properties
    from CRM import span, v, alpha, rho

    # Define spatialbeam properties
    from aluminum import E, G, stress, mrho

    # Create the mesh with 2 inboard points and 3 outboard points.
    # This will be mirrored to produce a mesh with 7 spanwise points,
    # or 6 spanwise panels
    # print(type(num_inboard))
    mesh = gen_crm_mesh(int(num_inboard), int(num_outboard), num_x=2)
    num_x, num_y = mesh.shape[:2]
    num_twist = np.max([int((num_y - 1) / 5), 5])
    r = radii(mesh)

    # Set the number of thickness control points and the initial thicknesses
    num_thickness = num_twist
    t = r / 10

    mesh = mesh.reshape(-1, mesh.shape[-1])
    aero_ind = np.atleast_2d(np.array([num_x, num_y]))
    fem_ind = [num_y]
    aero_ind, fem_ind = get_inds(aero_ind, fem_ind)

    # Set additional mesh parameters
    dihedral = 0.  # dihedral angle in degrees
    sweep = 0.  # shearing sweep angle in degrees
    taper = 1.  # taper ratio

    # Initial displacements of zero
    tot_n_fem = np.sum(fem_ind[:, 0])
    disp = np.zeros((tot_n_fem, 6))

    # Define Jacobians for b-spline controls
    tot_n_fem = np.sum(fem_ind[:, 0])
    num_surf = fem_ind.shape[0]
    jac_twist = get_bspline_mtx(num_twist, num_y)
    jac_thickness = get_bspline_mtx(num_thickness, tot_n_fem - num_surf)

    # Define ...
    twist_cp = np.zeros(num_twist)
    thickness_cp = np.ones(num_thickness) * np.max(t)

    # Define the design variables
    des_vars = [('twist_cp', twist_cp), ('dihedral', dihedral),
                ('sweep', sweep), ('span', span), ('taper', taper), ('v', v),
                ('alpha', alpha), ('rho', rho), ('disp', disp),
                ('aero_ind', aero_ind), ('fem_ind', fem_ind)]

    root = Group()

    root.add(
        'des_vars',
        IndepVarComp(des_vars),
        promotes=['twist_cp', 'span', 'v', 'alpha', 'rho', 'disp', 'dihedral'])
    root.add(
        'mesh',  # This component is needed, otherwise resulting loads matrix is NaN
        GeometryMesh(
            mesh,
            aero_ind),  # changes mesh given span, sweep, twist, and des_vars
        promotes=['span', 'sweep', 'dihedral', 'twist', 'taper', 'mesh'])
    root.add('def_mesh',
             TransferDisplacements(aero_ind, fem_ind),
             promotes=['mesh', 'disp', 'def_mesh'])

    prob = Problem()
    prob.root = root
    prob.setup(check=check, out_stream=out_stream)
    prob.run()

    # Output the def_mesh for the aero modules
    def_mesh = prob['def_mesh']

    # Other variables needed for aero and struct modules
    params = {
        'mesh': mesh,
        'num_x': num_x,
        'num_y': num_y,
        'span': span,
        'twist_cp': twist_cp,
        'thickness_cp': thickness_cp,
        'v': v,
        'alpha': alpha,
        'rho': rho,
        'r': r,
        't': t,
        'aero_ind': aero_ind,
        'fem_ind': fem_ind,
        'num_thickness': num_thickness,
        'num_twist': num_twist,
        'sweep': sweep,
        'taper': taper,
        'dihedral': dihedral,
        'E': E,
        'G': G,
        'stress': stress,
        'mrho': mrho,
        'tot_n_fem': tot_n_fem,
        'num_surf': num_surf,
        'jac_twist': jac_twist,
        'jac_thickness': jac_thickness,
        'out_stream': out_stream,
        'check': check
    }

    return (def_mesh, params)
Ejemplo n.º 8
0
        ####################################
        indep_vars = [('span', span), ('twist', numpy.zeros(num_twist)),
                      ('dihedral', 0.), ('sweep', 0.), ('taper', 1.0),
                      ('v', v), ('alpha', alpha), ('rho', rho), ('r', r),
                      ('thick', thick), ('zeta', zeta)]

        #######################
        # Calls of components #
        #######################
        root = Group()

        # Components before the time loop
        root.add('indep_vars', IndepVarComp(indep_vars), promotes=['*'])
        root.add('tube', MaterialsTube(num_y_sym), promotes=['*'])
        root.add('mesh',
                 GeometryMesh(full_wing_mesh, num_twist),
                 promotes=['*'])
        root.add('matrices',
                 SpatialBeamMatrices(num_x, num_y_sym, E, G, mrho, fem_origin),
                 promotes=['*'])
        SBEIG = SpatialBeamEIG(num_y_sym, num_dt, final_t)
        root.add('eig', SBEIG, promotes=['*'])

        # Time loop
        coupled = Group()
        for t in xrange(num_dt):
            name_step = 'step_%d' % t
            coupled.add(name_step,
                        SingleStep(num_x, num_y_sym, num_w, E, G, mrho,
                                   fem_origin, SBEIG, t),
                        promotes=['*'])
Ejemplo n.º 9
0
root = Group()

des_vars = [
    ('twist', numpy.zeros(num_twist)),
    ('span', span),
    ('v', v),
    ('alpha', alpha),
    ('rho', rho),
    ('disp', numpy.zeros((num_y, 6)))
]

root.add('des_vars',
         IndepVarComp(des_vars),
         promotes=['*'])
root.add('mesh',
         GeometryMesh(mesh, aero_ind, num_twist),
         promotes=['*'])
root.add('def_mesh',
         TransferDisplacements(aero_ind),
         promotes=['*'])
root.add('vlmstates',
         VLMStates(aero_ind),
         promotes=['*'])
root.add('vlmfuncs',
         VLMFunctionals(aero_ind, CL0, CD0, num_twist),
         promotes=['*'])

prob = Problem()
prob.root = root

prob.setup()
Ejemplo n.º 10
0
    ('t', t),
    ('aero_ind', aero_ind)
]

############################################################
# These are your components, put them in the correct groups.
# indep_vars_comp, tube_comp, and weiss_func_comp have been
# done for you as examples
############################################################

indep_vars_comp = IndepVarComp(indep_vars)
twist_comp = Bspline('twist_cp', 'twist', jac_twist)
thickness_comp = Bspline('thickness_cp', 'thickness', jac_thickness)
tube_comp = MaterialsTube(fem_ind)

mesh_comp = GeometryMesh(mesh, aero_ind)
spatialbeamstates_comp = SpatialBeamStates(aero_ind, fem_ind, E, G)
def_mesh_comp = TransferDisplacements(aero_ind, fem_ind)
vlmstates_comp = VLMStates(aero_ind)
loads_comp = TransferLoads(aero_ind, fem_ind)

vlmfuncs_comp = VLMFunctionals(aero_ind, CL0, CD0)
spatialbeamfuncs_comp = SpatialBeamFunctionals(aero_ind, fem_ind, E, G, stress, mrho)
fuelburn_comp = FunctionalBreguetRange(W0, CT, a, R, M, aero_ind)
eq_con_comp = FunctionalEquilibrium(W0, aero_ind)

############################################################
############################################################

root.add('indep_vars',
         indep_vars_comp,
Ejemplo n.º 11
0
    def setup_aerostruct(self):
        """
        Specific method to add the necessary components to the problem for an
        aerostructural problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'aerostruct'

        # Create the base root-level group
        root = Group()
        coupled = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']
            tmp_group = Group()

            # Add independent variables that do not belong to a specific component
            indep_vars = [
                (name + 'twist_cp', numpy.zeros(surface['num_twist'])),
                (name + 'thickness_cp', numpy.ones(surface['num_thickness']) *
                 numpy.max(surface['t'])), (name + 'r', surface['r']),
                (name + 'dihedral', surface['dihedral']),
                (name + 'sweep', surface['sweep']),
                (name + 'span', surface['span']),
                (name + 'taper', surface['taper'])
            ]

            # Obtain the Jacobians to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])
            jac_thickness = get_bspline_mtx(surface['num_thickness'],
                                            surface['num_y'] - 1)

            # Add components to include in the '_pre_solve' group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline(name + 'twist_cp', name + 'twist',
                                  jac_twist),
                          promotes=['*'])
            tmp_group.add('thickness_bsp',
                          Bspline(name + 'thickness_cp', name + 'thickness',
                                  jac_thickness),
                          promotes=['*'])
            tmp_group.add('tube', MaterialsTube(surface), promotes=['*'])

            # Add tmp_group to the problem with the name of the surface and
            # '_pre_solve' appended.
            name_orig = name  #.strip('_')
            name = name + 'pre_solve'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=["*"])')

            # Add components to the 'coupled' group for each surface
            tmp_group = Group()
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('def_mesh',
                          TransferDisplacements(surface),
                          promotes=['*'])
            tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*'])
            tmp_group.add('spatialbeamstates',
                          SpatialBeamStates(surface),
                          promotes=['*'])
            tmp_group.spatialbeamstates.ln_solver = LinearGaussSeidel()

            name = name_orig + 'group'
            exec(name + ' = tmp_group')
            exec('coupled.add("' + name + '", ' + name + ', promotes=["*"])')

            # Add a loads component to the coupled group
            exec('coupled.add("' + name_orig + 'loads' + '", ' +
                 'TransferLoads(surface)' + ', promotes=["*"])')

            # Add a '_post_solve' group which evaluates the data after solving
            # the coupled system
            tmp_group = Group()

            tmp_group.add('spatialbeamfuncs',
                          SpatialBeamFunctionals(surface),
                          promotes=['*'])
            tmp_group.add('vlmfuncs', VLMFunctionals(surface), promotes=['*'])

            name = name_orig + 'post_solve'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=["*"])')

        # Add a single 'VLMStates' component for the whole system
        coupled.add('vlmstates',
                    VLMStates(self.surfaces, self.prob_dict),
                    promotes=['*'])

        # Set solver properties for the coupled group
        coupled.ln_solver = ScipyGMRES()
        coupled.ln_solver.options['iprint'] = 1
        coupled.ln_solver.preconditioner = LinearGaussSeidel()
        coupled.vlmstates.ln_solver = LinearGaussSeidel()

        coupled.nl_solver = NLGaussSeidel()
        coupled.nl_solver.options['iprint'] = 1

        # Ensure that the groups are ordered correctly within the coupled group
        order_list = []
        for surface in self.surfaces:
            order_list.append(surface['name'] + 'group')
        order_list.append('vlmstates')
        for surface in self.surfaces:
            order_list.append(surface['name'] + 'loads')
        coupled.set_order(order_list)

        # Add the coupled group to the root problem
        root.add('coupled', coupled, promotes=['*'])

        # Add problem information as an independent variables component
        prob_vars = [('v', self.prob_dict['v']),
                     ('alpha', self.prob_dict['alpha']),
                     ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']),
                     ('rho', self.prob_dict['rho'])]
        root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*'])

        # Add functionals to evaluate performance of the system
        root.add('fuelburn',
                 FunctionalBreguetRange(self.surfaces, self.prob_dict),
                 promotes=['*'])
        root.add('eq_con',
                 FunctionalEquilibrium(self.surfaces, self.prob_dict),
                 promotes=['*'])

        self.setup_prob()
Ejemplo n.º 12
0
    def setup_aero(self):
        """
        Specific method to add the necessary components to the problem for an
        aerodynamic problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'aero'

        # Create the base root-level group
        root = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']
            tmp_group = Group()

            # Add independent variables that do not belong to a specific component
            indep_vars = [(name + 'twist_cp',
                           numpy.zeros(surface['num_twist'])),
                          (name + 'dihedral', surface['dihedral']),
                          (name + 'sweep', surface['sweep']),
                          (name + 'span', surface['span']),
                          (name + 'taper', surface['taper']),
                          (name + 'disp', numpy.zeros((surface['num_y'], 6)))]

            # Obtain the Jacobian to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])

            # Add aero components to the surface-specific group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline(name + 'twist_cp', name + 'twist',
                                  jac_twist),
                          promotes=['*'])
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('def_mesh',
                          TransferDisplacements(surface),
                          promotes=['*'])
            tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*'])

            # Add tmp_group to the problem with the name of the surface and
            # '_pre_solve' appended.
            # Note that is a '_pre_solve' and '_post_solve' group for each
            # individual surface.
            name_orig = name.strip('_')
            name = name_orig + '_pre_solve'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=["*"])')

            # Add a '_post_solve' group
            name = name_orig + '_post_solve'
            exec('root.add("' + name + '", ' + 'VLMFunctionals(surface)' +
                 ', promotes=["*"])')

        # Add problem information as an independent variables component
        prob_vars = [('v', self.prob_dict['v']),
                     ('alpha', self.prob_dict['alpha']),
                     ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']),
                     ('rho', self.prob_dict['rho'])]
        root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*'])

        # Add a single 'VLMStates' component that solves for the circulations
        # and forces from all the surfaces.
        # While other components only depends on a single surface,
        # this component requires information from all surfaces because
        # each surface interacts with the others.
        root.add('vlmstates',
                 VLMStates(self.surfaces, self.prob_dict),
                 promotes=['*'])

        self.setup_prob()
Ejemplo n.º 13
0
def setup(prob_dict={}, surfaces=[{}]):
    ''' Setup the aerostruct mesh

    Default wing mesh (single lifting surface):
    -------------------------------------------
    name = 'wing'            # name of the surface
    num_x = 3                # number of chordwise points
    num_y = 5                # number of spanwise points
    root_chord = 1.          # root chord
    span_cos_spacing = 1     # 0 for uniform spanwise panels
                             # 1 for cosine-spaced panels
                             # any value between 0 and 1 for a mixed spacing
    chord_cos_spacing = 0.   # 0 for uniform chordwise panels
                             # 1 for cosine-spaced panels
                             # any value between 0 and 1 for a mixed spacing
    wing_type = 'rect'       # initial shape of the wing either 'CRM' or 'rect'
                             # 'CRM' can have different options after it, such as 'CRM:alpha_2.75' for the CRM shape at alpha=2.75
    offset = np.array([0., 0., 0.]) # coordinates to offset the surface from its default location
    symmetry = True          # if true, model one half of wing reflected across the plane y = 0
    S_ref_type = 'wetted'    # 'wetted' or 'projected'

    # Simple Geometric Variables
    span = 10.               # full wingspan
    dihedral = 0.            # wing dihedral angle in degrees positive is upward
    sweep = 0.               # wing sweep angle in degrees positive sweeps back
    taper = 1.               # taper ratio; 1. is uniform chord

    # B-spline Geometric Variables. The number of control points for each of these variables can be specified in surf_dict
    # by adding the prefix "num" to the variable (e.g. num_twist)
    twist_cp = None
    chord_cp = None
    xshear_cp = None
    zshear_cp = None
    thickness_cp = None

    Default wing parameters:
    ------------------------
    Zero-lift aerodynamic performance
        CL0 = 0.0            # CL value at AoA (alpha) = 0
        CD0 = 0.0            # CD value at AoA (alpha) = 0
    Airfoil properties for viscous drag calculation
        k_lam = 0.05         # percentage of chord with laminar flow, used for viscous drag
        t_over_c = 0.12      # thickness over chord ratio (NACA0012)
        c_max_t = .303       # chordwise location of maximum (NACA0012) thickness
    Structural values are based on aluminum
        E = 70.e9            # [Pa] Young's modulus of the spar
        G = 30.e9            # [Pa] shear modulus of the spar
        stress = 20.e6       # [Pa] yield stress
        mrho = 3.e3          # [kg/m^3] material density
        fem_origin = 0.35    # chordwise location of the spar
    Other
        W0 = 0.4 * 3e5       # [kg] MTOW of B777 is 3e5 kg with fuel

    Default problem parameters:
    ---------------------------
    Re = 1e6                 # Reynolds number
    reynolds_length = 1.0    # characteristic Reynolds length
    alpha = 5.               # angle of attack
    CT = 9.80665 * 17.e-6    # [1/s] (9.81 N/kg * 17e-6 kg/N/s)
    R = 14.3e6               # [m] maximum range
    M = 0.84                 # Mach number at cruise
    rho = 0.38               # [kg/m^3] air density at 35,000 ft
    a = 295.4                # [m/s] speed of sound at 35,000 ft
    with_viscous = False     # if true, compute viscous drag

    '''
    # Use steps in run_aerostruct.py to add wing surface to problem

    # Set problem type
    prob_dict.update({
        'type': 'aerostruct'
    })  # this doesn't really matter since we aren't calling OASProblem.setup()

    # Instantiate problem
    OAS_prob = OASProblem(prob_dict)

    for surface in surfaces:
        # Add SpatialBeamFEM size
        FEMsize = 6 * surface['num_y'] + 6
        surface.update({'FEMsize': FEMsize})
        # Add the specified wing surface to the problem.
        OAS_prob.add_surface(surface)

    # Add materials properties for the wing surface to the surface dict in OAS_prob
    for idx, surface in enumerate(OAS_prob.surfaces):
        A, Iy, Iz, J = materials_tube(surface['radius'], surface['thickness'],
                                      surface)
        OAS_prob.surfaces[idx].update({'A': A, 'Iy': Iy, 'Iz': Iz, 'J': J})

    # Get total panels and save in prob_dict
    tot_panels = 0
    for surface in OAS_prob.surfaces:
        ny = surface['num_y']
        nx = surface['num_x']
        tot_panels += (nx - 1) * (ny - 1)
    OAS_prob.prob_dict.update({'tot_panels': tot_panels})

    # Assume we are only using a single lifting surface for now
    surface = OAS_prob.surfaces[0]

    # Initialize the OpenAeroStruct components and save them in a component dictionary
    comp_dict = {}
    comp_dict['MaterialsTube'] = MaterialsTube(surface)
    comp_dict['GeometryMesh'] = GeometryMesh(surface)
    comp_dict['TransferDisplacements'] = TransferDisplacements(surface)
    comp_dict['VLMGeometry'] = VLMGeometry(surface)
    comp_dict['AssembleAIC'] = AssembleAIC([surface])
    comp_dict['AeroCirculations'] = AeroCirculations(
        OAS_prob.prob_dict['tot_panels'])
    comp_dict['VLMForces'] = VLMForces([surface])
    comp_dict['TransferLoads'] = TransferLoads(surface)
    comp_dict['ComputeNodes'] = ComputeNodes(surface)
    comp_dict['AssembleK'] = AssembleK(surface)
    comp_dict['SpatialBeamFEM'] = SpatialBeamFEM(surface['FEMsize'])
    comp_dict['SpatialBeamDisp'] = SpatialBeamDisp(surface)
    OAS_prob.comp_dict = comp_dict

    return OAS_prob
Ejemplo n.º 14
0
    # Get total panels and save in prob_dict
    tot_panels = 0
    for surface in OAS_prob.surfaces:
        ny = surface['num_y']
        nx = surface['num_x']
        tot_panels += (nx - 1) * (ny - 1)
    OAS_prob.prob_dict.update({'tot_panels': tot_panels})

    # Assume we are only using a single lifting surface for now
    surface = OAS_prob.surfaces[0]

    # Initialize the OpenAeroStruct components and save them in a component dictionary
    comp_dict = {}
    comp_dict['MaterialsTube'] = MaterialsTube(surface)
    comp_dict['GeometryMesh'] = GeometryMesh(surface)
    comp_dict['TransferDisplacements'] = TransferDisplacements(surface)
    comp_dict['VLMGeometry'] = VLMGeometry(surface)
    comp_dict['AssembleAIC'] = AssembleAIC([surface])
    comp_dict['AeroCirculations'] = AeroCirculations(OAS_prob.prob_dict['tot_panels'])
    comp_dict['VLMForces'] = VLMForces([surface])
    comp_dict['TransferLoads'] = TransferLoads(surface)
    comp_dict['ComputeNodes'] = ComputeNodes(surface)
    comp_dict['AssembleK'] = AssembleK(surface)
    comp_dict['SpatialBeamFEM'] = SpatialBeamFEM(surface['FEMsize'])
    comp_dict['SpatialBeamDisp'] = SpatialBeamDisp(surface)
    OAS_prob.comp_dict = comp_dict

<<<<<<< HEAD
    # return the surfaces list, problem dict, and component dict
    surfaces = [surface]
Ejemplo n.º 15
0
    def setup_aerostruct(self):
        """
        Specific method to add the necessary components to the problem for an
        aerostructural problem.
        """

        # Set the problem name if the user doesn't
        if 'prob_name' not in self.prob_dict.keys():
            self.prob_dict['prob_name'] = 'aerostruct'

        # Create the base root-level group
        root = Group()
        coupled = Group()

        # Create the problem and assign the root group
        self.prob = Problem()
        self.prob.root = root

        # Loop over each surface in the surfaces list
        for surface in self.surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']
            tmp_group = Group()

            # Add independent variables that do not belong to a specific component
            indep_vars = [
                ('twist_cp', numpy.zeros(surface['num_twist'])),
                ('thickness_cp', numpy.ones(surface['num_thickness']) *
                 numpy.max(surface['t'])), ('r', surface['r']),
                ('dihedral', surface['dihedral']), ('sweep', surface['sweep']),
                ('span', surface['span']), ('taper', surface['taper'])
            ]

            # Obtain the Jacobians to interpolate the data from the b-spline
            # control points
            jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y'])
            jac_thickness = get_bspline_mtx(surface['num_thickness'],
                                            surface['num_y'] - 1)

            # Add components to include in the surface's group
            tmp_group.add('indep_vars',
                          IndepVarComp(indep_vars),
                          promotes=['*'])
            tmp_group.add('twist_bsp',
                          Bspline('twist_cp', 'twist', jac_twist),
                          promotes=['*'])
            tmp_group.add('thickness_bsp',
                          Bspline('thickness_cp', 'thickness', jac_thickness),
                          promotes=['*'])
            tmp_group.add('tube', MaterialsTube(surface), promotes=['*'])

            # Add tmp_group to the problem with the name of the surface.
            name_orig = name
            name = name[:-1]
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name + ', promotes=[])')

            # Add components to the 'coupled' group for each surface.
            # The 'coupled' group must contain all components and parameters
            # needed to converge the aerostructural system.
            tmp_group = Group()
            tmp_group.add('mesh', GeometryMesh(surface), promotes=['*'])
            tmp_group.add('def_mesh',
                          TransferDisplacements(surface),
                          promotes=['*'])
            tmp_group.add('aero_geom', VLMGeometry(surface), promotes=['*'])
            tmp_group.add('struct_states',
                          SpatialBeamStates(surface),
                          promotes=['*'])
            tmp_group.struct_states.ln_solver = LinearGaussSeidel()

            name = name_orig
            exec(name + ' = tmp_group')
            exec('coupled.add("' + name[:-1] + '", ' + name + ', promotes=[])')

            # Add a loads component to the coupled group
            exec('coupled.add("' + name_orig + 'loads' + '", ' +
                 'TransferLoads(surface)' + ', promotes=[])')

            # Add a performance group which evaluates the data after solving
            # the coupled system
            tmp_group = Group()

            tmp_group.add('struct_funcs',
                          SpatialBeamFunctionals(surface),
                          promotes=['*'])
            tmp_group.add('aero_funcs',
                          VLMFunctionals(surface),
                          promotes=['*'])

            name = name_orig + 'perf'
            exec(name + ' = tmp_group')
            exec('root.add("' + name + '", ' + name +
                 ', promotes=["rho", "v", "alpha", "Re", "M"])')

        # Add a single 'aero_states' component for the whole system within the
        # coupled group.
        coupled.add('aero_states',
                    VLMStates(self.surfaces, self.prob_dict),
                    promotes=['v', 'alpha', 'rho'])

        # Explicitly connect parameters from each surface's group and the common
        # 'aero_states' group.
        for surface in self.surfaces:
            name = surface['name']

            # Perform the connections with the modified names within the
            # 'aero_states' group.
            root.connect('coupled.' + name[:-1] + '.def_mesh',
                         'coupled.aero_states.' + name + 'def_mesh')
            root.connect('coupled.' + name[:-1] + '.b_pts',
                         'coupled.aero_states.' + name + 'b_pts')
            root.connect('coupled.' + name[:-1] + '.c_pts',
                         'coupled.aero_states.' + name + 'c_pts')
            root.connect('coupled.' + name[:-1] + '.normals',
                         'coupled.aero_states.' + name + 'normals')

            # Connect the results from 'aero_states' to the performance groups
            root.connect('coupled.aero_states.' + name + 'sec_forces',
                         name + 'perf' + '.sec_forces')

            # Connect the results from 'coupled' to the performance groups
            root.connect('coupled.' + name[:-1] + '.def_mesh',
                         'coupled.' + name + 'loads.def_mesh')
            root.connect('coupled.aero_states.' + name + 'sec_forces',
                         'coupled.' + name + 'loads.sec_forces')
            root.connect('coupled.' + name + 'loads.loads',
                         name + 'perf.loads')

            # Connect the output of the loads component with the FEM
            # displacement parameter. This links the coupling within the coupled
            # group that necessitates the subgroup solver.
            root.connect('coupled.' + name + 'loads.loads',
                         'coupled.' + name[:-1] + '.loads')

            # Connect aerodyamic design variables
            root.connect(name[:-1] + '.dihedral',
                         'coupled.' + name[:-1] + '.dihedral')
            root.connect(name[:-1] + '.span', 'coupled.' + name[:-1] + '.span')
            root.connect(name[:-1] + '.sweep',
                         'coupled.' + name[:-1] + '.sweep')
            root.connect(name[:-1] + '.taper',
                         'coupled.' + name[:-1] + '.taper')
            root.connect(name[:-1] + '.twist',
                         'coupled.' + name[:-1] + '.twist')

            # Connect structural design variables
            root.connect(name[:-1] + '.A', 'coupled.' + name[:-1] + '.A')
            root.connect(name[:-1] + '.Iy', 'coupled.' + name[:-1] + '.Iy')
            root.connect(name[:-1] + '.Iz', 'coupled.' + name[:-1] + '.Iz')
            root.connect(name[:-1] + '.J', 'coupled.' + name[:-1] + '.J')

            # Connect performance calculation variables
            root.connect(name[:-1] + '.r', name + 'perf.r')
            root.connect(name[:-1] + '.A', name + 'perf.A')

            # Connection performance functional variables
            root.connect(name + 'perf.weight', 'fuelburn.' + name + 'weight')
            root.connect(name + 'perf.weight', 'eq_con.' + name + 'weight')
            root.connect(name + 'perf.L', 'eq_con.' + name + 'L')
            root.connect(name + 'perf.CL', 'fuelburn.' + name + 'CL')
            root.connect(name + 'perf.CD', 'fuelburn.' + name + 'CD')

            # Connect paramters from the 'coupled' group to the performance
            # group.
            root.connect('coupled.' + name[:-1] + '.nodes',
                         name + 'perf.nodes')
            root.connect('coupled.' + name[:-1] + '.disp', name + 'perf.disp')
            root.connect('coupled.' + name[:-1] + '.S_ref',
                         name + 'perf.S_ref')

        # Set solver properties for the coupled group
        coupled.ln_solver = ScipyGMRES()
        coupled.ln_solver.options['iprint'] = 1
        coupled.ln_solver.preconditioner = LinearGaussSeidel()
        coupled.aero_states.ln_solver = LinearGaussSeidel()

        coupled.nl_solver = NLGaussSeidel()
        coupled.nl_solver.options['iprint'] = 1

        # Ensure that the groups are ordered correctly within the coupled group
        # so that a system with multiple surfaces is solved corretly.
        order_list = []
        for surface in self.surfaces:
            order_list.append(surface['name'][:-1])
        order_list.append('aero_states')
        for surface in self.surfaces:
            order_list.append(surface['name'] + 'loads')
        coupled.set_order(order_list)

        # Add the coupled group to the root problem
        root.add('coupled', coupled, promotes=['v', 'alpha', 'rho'])

        # Add problem information as an independent variables component
        prob_vars = [('v', self.prob_dict['v']),
                     ('alpha', self.prob_dict['alpha']),
                     ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']),
                     ('rho', self.prob_dict['rho'])]
        root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*'])

        # Add functionals to evaluate performance of the system.
        # Note that only the interesting results are promoted here; not all
        # of the parameters.
        root.add('fuelburn',
                 FunctionalBreguetRange(self.surfaces, self.prob_dict),
                 promotes=['fuelburn'])
        root.add('eq_con',
                 FunctionalEquilibrium(self.surfaces, self.prob_dict),
                 promotes=['eq_con', 'fuelburn'])

        # Actually set up the system
        self.setup_prob()
Ejemplo n.º 16
0
def struct(loads, params):

    # Unpack variables
    mesh = params.get('mesh')
    num_x = params.get('num_x')
    num_y = params.get('num_y')
    span = params.get('span')
    twist_cp = params.get('twist_cp')
    thickness_cp = params.get('thickness_cp')
    v = params.get('v')
    alpha = params.get('alpha')
    rho = params.get('rho')
    r = params.get('r')
    t = params.get('t')
    aero_ind = params.get('aero_ind')
    fem_ind = params.get('fem_ind')
    num_thickness = params.get('num_thickness')
    num_twist = params.get('num_twist')
    sweep = params.get('sweep')
    taper = params.get('taper')
    disp = params.get('disp')
    dihedral = params.get('dihedral')
    E = params.get('E')
    G = params.get('G')
    stress = params.get('stress')
    mrho = params.get('mrho')
    tot_n_fem = params.get('tot_n_fem')
    num_surf = params.get('num_surf')
    jac_twist = params.get('jac_twist')
    jac_thickness = params.get('jac_thickness')
    check = params.get('check')
    out_stream = params.get('out_stream')

    # Define the design variables
    des_vars = [
        ('twist_cp', twist_cp),
        ('thickness_cp', thickness_cp),
        ('r', r),
        # ('dihedral', dihedral),
        # ('sweep', sweep),
        # ('span', span),
        # ('taper', taper),
        # ('v', v),
        # ('alpha', alpha),
        # ('rho', rho),
        # ('disp', disp),
        ('loads', loads)
    ]

    root = Group()

    root.add(
        'des_vars',
        IndepVarComp(des_vars),
        #  promotes=['thickness_cp','r','loads'])
        promotes=['*'])
    # root.add('twist_bsp',  # What is this doing?
    #          Bspline('twist_cp', 'twist', jac_twist),
    #          promotes=['*'])
    root.add('twist_bsp',
             Bspline('twist_cp', 'twist', jac_twist),
             promotes=['*'])
    root.add(
        'thickness_bsp',  # What is this doing?
        Bspline('thickness_cp', 'thickness', jac_thickness),
        #  promotes=['thickness'])
        promotes=['*'])
    root.add('mesh', GeometryMesh(mesh, aero_ind), promotes=['*'])
    root.add(
        'tube',
        MaterialsTube(fem_ind),
        #  promotes=['r','thickness','A','Iy','Iz','J'])
        promotes=['*'])
    root.add(
        'spatialbeamstates',
        SpatialBeamStates(aero_ind, fem_ind, E, G),
        #  promotes=[
        #     'mesh', # ComputeNodes
        #     'A','Iy','Iz','J','loads', # SpatialBeamFEM
        #     'disp' # SpatialBeamDisp
        #  ])
        promotes=['*'])
    root.add(
        'transferdisp',
        TransferDisplacements(aero_ind, fem_ind),
        #  promotes=['mesh','disp','def_mesh'])
        promotes=['*'])

    prob = Problem()
    prob.root = root
    prob.setup(check=check, out_stream=out_stream)
    prob.run()

    return prob['def_mesh']  # Output the def_mesh matrix
Ejemplo n.º 17
0
    # These will be used in the analysis and optimization and will connect
    # to variables within the components.
    # For example, here we set the loads, and SpatialBeamStates computes
    # the displacements based off of these loads.
    des_vars = [('twist', numpy.zeros(surface['num_y'])),
                ('span', surface['span']), ('r', r), ('thickness', thickness),
                ('loads', loads)]

    # Add components to the root problem. Note that each of the components
    # is defined with `promotes=['*']`, which means that all parameters
    # within that component are promoted to the root level so that all
    # other components can access them. For example, GeometryMesh creates
    # the mesh, and SpatialBeamStates uses this mesh information.
    # The data passing happens behind-the-scenes in OpenMDAO.
    root.add('des_vars', IndepVarComp(des_vars), promotes=['*'])
    root.add('mesh', GeometryMesh(surface), promotes=['*'])
    root.add('tube', MaterialsTube(surface), promotes=['*'])
    root.add('spatialbeamstates', SpatialBeamStates(surface), promotes=['*'])
    root.add('spatialbeamfuncs',
             SpatialBeamFunctionals(surface),
             promotes=['*'])

    # Instantiate an OpenMDAO problem and all the root group that we just
    # created to the problem.
    prob = Problem()
    prob.root = root

    # Set a driver for the optimization problem. Without a driver, OpenMDAO
    # doesn't know how to change the parameters to achieve an optimal solution.
    # There are a few options, but ScipyOptimizer and SLSQP are generally
    # the best options to use without installing additional packages.
Ejemplo n.º 18
0
for ind_x in xrange(num_x):
    for ind_y in xrange(num_y):
        mesh[ind_x,
             ind_y, :] = [ind_x / (num_x - 1) * chord, full_wing[ind_y],
                          0]  # straight elliptical spacing

aero_ind = numpy.atleast_2d(numpy.array([num_x, num_y]))
mesh = mesh.reshape(-1, mesh.shape[-1])

root = Group()

des_vars = [('twist', numpy.zeros(num_twist)), ('span', span), ('v', v),
            ('alpha', alpha), ('rho', rho), ('disp', numpy.zeros((num_y, 6)))]

root.add('des_vars', IndepVarComp(des_vars), promotes=['*'])
root.add('mesh', GeometryMesh(mesh, aero_ind, num_twist), promotes=['*'])
root.add('def_mesh', TransferDisplacements(aero_ind), promotes=['*'])
root.add('vlmstates', VLMStates(aero_ind), promotes=['*'])
root.add('vlmfuncs',
         VLMFunctionals(aero_ind, CL0, CD0, num_twist),
         promotes=['*'])

prob = Problem()
prob.root = root

prob.setup()

alpha_start = -3.
alpha_stop = 14
num_alpha = 18.