Ejemplo n.º 1
0
def transfer_displacements(mesh, disp, comp):
    """
    Perform displacement transfer.

    Apply the computed displacements on the original mesh to obtain
    the deformed mesh.

    Parameters
    ----------
    mesh[nx, ny, 3] : numpy array
        Flattened array defining the lifting surfaces.
    disp[ny, 6] : numpy array
        Flattened array containing displacements on the FEM component.
        Contains displacements for all six degrees of freedom, including
        displacements in the x, y, and z directions, and rotations about the
        x, y, and z axes.
    comp : Either OpenAeroStruct component object (better), or surface dict.

    Returns
    -------
    def_mesh[nx, ny, 3] : numpy array
        Flattened array defining the lifting surfaces after deformation.
    """
    if not isinstance(comp, Component):
        surface = comp
        comp = TransferDisplacements(surface)
    params = {'mesh': mesh, 'disp': disp}
    unknowns = {'def_mesh': np.zeros((comp.nx, comp.ny, 3), dtype=data_type)}
    resids = None
    comp.solve_nonlinear(params, unknowns, resids)
    def_mesh = unknowns.get('def_mesh')
    return def_mesh
Ejemplo n.º 2
0
    def __init__(self, num_x, num_y, num_w, E, G, mrho, fem_origin, SBEIG, t):
        super(SingleStep, self).__init__()

        name_def_mesh = 'def_mesh_%d' % t
        name_vlmstates = 'vlmstates_%d' % t
        name_loads = 'loads_%d' % t
        name_spatialbeamstates = 'spatialbeamstates_%d' % t

        self.add_subsystem(name_def_mesh,
                           TransferDisplacements(nx=num_x,
                                                 n=num_y,
                                                 t=t,
                                                 fem_origin=fem_origin),
                           promotes=['*'])
        self.add_subsystem(name_vlmstates,
                           UVLMStates(num_x, num_y, num_w, t),
                           promotes=['*'])
        self.add_subsystem(name_loads,
                           TransferLoads(nx=num_x,
                                         n=num_y,
                                         t=t,
                                         fem_origin=fem_origin),
                           promotes=['*'])
        self.add_subsystem(name_spatialbeamstates,
                           SpatialBeamStates(num_x, num_y, E, G, mrho, SBEIG,
                                             t),
                           promotes=['*'])
Ejemplo n.º 3
0
def transfer_displacements(mesh, disp, comp):
    """
    Perform displacement transfer.

    Apply the computed displacements on the original mesh to obtain
    the deformed mesh.

    Parameters
    ----------
    mesh[nx, ny, 3] : numpy array
        Flattened array defining the lifting surfaces.
    disp[ny, 6] : numpy array
        Flattened array containing displacements on the FEM component.
        Contains displacements for all six degrees of freedom, including
        displacements in the x, y, and z directions, and rotations about the
        x, y, and z axes.
    comp : Either OpenAeroStruct component object (better), or surface dict.

    Returns
    -------
    def_mesh[nx, ny, 3] : numpy array
        Flattened array defining the lifting surfaces after deformation.
    """
    if not isinstance(comp, Component):
        surface = comp
        comp = TransferDisplacements(surface)
    params = {
        'mesh': mesh,
        'disp': disp
    }
    unknowns = {
        'def_mesh': np.zeros((comp.nx, comp.ny, 3), dtype=data_type)
    }
    resids = None
    comp.solve_nonlinear(params, unknowns, resids)
    def_mesh = unknowns.get('def_mesh')
    return def_mesh
Ejemplo n.º 4
0
    def __init__(self, num_x, num_y, num_w, E, G, mrho, fem_origin, t):
        super(SingleAeroStep, self).__init__()

        name_def_mesh = 'def_mesh_%d' % t
        name_vlmstates = 'vlmstates_%d' % t
        name_loads = 'loads_%d' % t
        name_spatialbeamstates = 'spatialbeamstates_%d' % t

        self.add(name_def_mesh,
                 TransferDisplacements(num_x, num_y, t, fem_origin),
                 promotes=['*'])
        self.add(name_vlmstates,
                 UVLMStates(num_x, num_y, num_w, t),
                 promotes=['*'])
        self.add(name_loads,
                 TransferLoads(num_x, num_y, t, fem_origin),
                 promotes=['*'])
Ejemplo n.º 5
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.º 6
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.º 7
0
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()
coupled.add('mesh', mesh_comp, promotes=["*"])
coupled.add('spatialbeamstates', spatialbeamstates_comp, promotes=["*"])
Ejemplo n.º 8
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.º 9
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]
    prob_dict = OAS_prob.prob_dict
Ejemplo n.º 10
0
    ('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
Ejemplo n.º 11
0
    ('t', t),
]

root.add('des_vars',
         IndepVarComp(des_vars),
         promotes=['*'])
root.add('tube',
         MaterialsTube(num_y),
         promotes=['*'])

coupled = Group() # add components for MDA to this group
coupled.add('mesh',
            GeometryMesh(mesh, aero_ind, num_twist),
            promotes=['*'])
coupled.add('def_mesh',
            TransferDisplacements(num_y),
            promotes=['*'])
coupled.add('vlmstates',
            VLMStates(num_y),
            promotes=['*'])
coupled.add('loads',
            TransferLoads(num_y),
            promotes=['*'])
coupled.add('spatialbeamstates',
            SpatialBeamStates(num_y, cons, E, G),
            promotes=['*'])

coupled.nl_solver = Newton()
coupled.nl_solver.options['iprint'] = 1
coupled.nl_solver.line_search.options['iprint'] = 1
Ejemplo n.º 12
0
]

############################################################
# 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,
         promotes=['*'])
root.add('twist_bsp',
Ejemplo n.º 13
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.º 14
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.º 15
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.º 16
0
        ('M', prob_dict['M']),
        ('Re', prob_dict['Re']),
    ]

    ###############################################################
    # Problem 2a:
    # These are your components. Here we simply create the objects.
    ###############################################################

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

    mesh_comp = GeometryMesh(surface)
    geom_comp = VLMGeometry(surface)
    spatialbeamstates_comp = SpatialBeamStates(surface)
    def_mesh_comp = TransferDisplacements(surface)
    vlmstates_comp = VLMStates(OAS_prob.surfaces, OAS_prob.prob_dict)
    loads_comp = TransferLoads(surface)

    vlmfuncs_comp = VLMFunctionals(surface)
    spatialbeamfuncs_comp = SpatialBeamFunctionals(surface)
    fuelburn_comp = FunctionalBreguetRange(OAS_prob.surfaces,
                                           OAS_prob.prob_dict)
    eq_con_comp = FunctionalEquilibrium(OAS_prob.surfaces, OAS_prob.prob_dict)

    #################################################################
    # Problem 2a:
    # Now add the components you created above to the correct groups.
    # indep_vars_comp, tube_comp, and vlm_funcs have been
    # done for you as examples.
    #################################################################
Ejemplo n.º 17
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.º 18
0
    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.

a_list = []