Ejemplo n.º 1
0
def vlm_geometry(def_mesh, comp):
    """ Compute various geometric properties for VLM analysis.

    Parameters
    ----------
    def_mesh[nx, ny, 3] : numpy array
        Array defining the nodal coordinates of the lifting surface.
    comp : Either OpenAeroStruct component object (better), or surface dict.

    Returns
    -------
    b_pts[nx-1, ny, 3] : numpy array
        Bound points for the horseshoe vortices, found along the 1/4 chord.
    c_pts[nx-1, ny-1, 3] : numpy array
        Collocation points on the 3/4 chord line where the flow tangency
        condition is satisfed. Used to set up the linear system.
    widths[nx-1, ny-1] : numpy array
        The spanwise widths of each individual panel.
    lengths[ny] : numpy array
        The chordwise length of the entire airfoil following the camber line.
    normals[nx-1, ny-1, 3] : numpy array
        The normal vector for each panel, computed as the cross of the two
        diagonals from the mesh points.
    S_ref : float
        The reference area of the lifting surface.
    """
    if not isinstance(comp, Component):
        surface = comp
        comp = VLMGeometry(surface)
    params = {
        'def_mesh': def_mesh
    }
    unknowns = {
        'b_pts': np.zeros((comp.nx-1, comp.ny, 3), dtype=data_type),
        'c_pts': np.zeros((comp.nx-1, comp.ny-1, 3)),
        'widths': np.zeros((comp.ny-1)),
        'cos_sweep': np.zeros((comp.ny-1)),
        'lengths': np.zeros((comp.ny)),
        'normals': np.zeros((comp.nx-1, comp.ny-1, 3)),
        'S_ref': 0.
    }
    resids=None
    comp.solve_nonlinear(params, unknowns, resids)
    b_pts=unknowns.get('b_pts')
    c_pts=unknowns.get('c_pts')
    widths=unknowns.get('widths')
    cos_sweep=unknowns.get('cos_sweep')
    lengths=unknowns.get('lengths')
    normals=unknowns.get('normals')
    S_ref=unknowns.get('S_ref')
    return b_pts, c_pts, widths, cos_sweep, lengths, normals, S_ref
Ejemplo n.º 2
0
def vlm_geometry(def_mesh, comp):
    """ Compute various geometric properties for VLM analysis.

    Parameters
    ----------
    def_mesh[nx, ny, 3] : numpy array
        Array defining the nodal coordinates of the lifting surface.
    comp : Either OpenAeroStruct component object (better), or surface dict.

    Returns
    -------
    b_pts[nx-1, ny, 3] : numpy array
        Bound points for the horseshoe vortices, found along the 1/4 chord.
    c_pts[nx-1, ny-1, 3] : numpy array
        Collocation points on the 3/4 chord line where the flow tangency
        condition is satisfed. Used to set up the linear system.
    widths[nx-1, ny-1] : numpy array
        The spanwise widths of each individual panel.
    lengths[ny] : numpy array
        The chordwise length of the entire airfoil following the camber line.
    normals[nx-1, ny-1, 3] : numpy array
        The normal vector for each panel, computed as the cross of the two
        diagonals from the mesh points.
    S_ref : float
        The reference area of the lifting surface.
    """
    if not isinstance(comp, Component):
        surface = comp
        comp = VLMGeometry(surface)
    params = {'def_mesh': def_mesh}
    unknowns = {
        'b_pts': np.zeros((comp.nx - 1, comp.ny, 3), dtype=data_type),
        'c_pts': np.zeros((comp.nx - 1, comp.ny - 1, 3)),
        'widths': np.zeros((comp.ny - 1)),
        'cos_sweep': np.zeros((comp.ny - 1)),
        'lengths': np.zeros((comp.ny)),
        'normals': np.zeros((comp.nx - 1, comp.ny - 1, 3)),
        'S_ref': 0.
    }
    resids = None
    comp.solve_nonlinear(params, unknowns, resids)
    b_pts = unknowns.get('b_pts')
    c_pts = unknowns.get('c_pts')
    widths = unknowns.get('widths')
    cos_sweep = unknowns.get('cos_sweep')
    lengths = unknowns.get('lengths')
    normals = unknowns.get('normals')
    S_ref = unknowns.get('S_ref')
    return b_pts, c_pts, widths, cos_sweep, lengths, normals, S_ref
Ejemplo n.º 3
0
        ('rho', prob_dict['rho']),
        ('r', r),
        ('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
Ejemplo n.º 4
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.º 5
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.º 6
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.º 7
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.º 8
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.º 9
0
    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
    # return surfaces, prob_dict, comp_dict