Exemplo n.º 1
0
    def setup(self):
        surface = self.options['surface']
        DVGeo = self.options['DVGeo']
        connect_geom_DVs = self.options['connect_geom_DVs']

        geom_promotes = []

        if 'twist_cp' in surface.keys():
            geom_promotes.append('twist_cp')
        if 't_over_c_cp' in surface.keys():
            geom_promotes.append('t_over_c')
        if 'sweep' in surface.keys():
            geom_promotes.append('sweep')
        if 'taper' in surface.keys():
            geom_promotes.append('taper')
        if 'mx' in surface.keys():
            geom_promotes.append('shape')

        self.add_subsystem('geometry',
            Geometry(surface=surface, DVGeo=DVGeo, connect_geom_DVs=connect_geom_DVs),
            promotes_inputs=[],
            promotes_outputs=['mesh'] + geom_promotes)

        if surface['fem_model_type'] == 'tube':
            tube_promotes = []
            tube_inputs = []
            if 'thickness_cp' in surface.keys():
                tube_promotes.append('thickness_cp')
            if 'radius_cp' not in surface.keys():
                tube_inputs = ['mesh', 't_over_c']
            self.add_subsystem('tube_group',
                TubeGroup(surface=surface),
                promotes_inputs=tube_inputs,
                promotes_outputs=['A', 'Iy', 'Iz', 'J', 'radius', 'thickness'] + tube_promotes)
        elif surface['fem_model_type'] == 'wingbox':
            wingbox_promotes = []
            if 'skin_thickness_cp' in surface.keys() and 'spar_thickness_cp' in surface.keys():
                wingbox_promotes.append('skin_thickness_cp')
                wingbox_promotes.append('spar_thickness_cp')
                wingbox_promotes.append('skin_thickness')
                wingbox_promotes.append('spar_thickness')
            elif 'skin_thickness_cp' in surface.keys() or 'spar_thickness_cp' in surface.keys():
                raise NameError('Please have both skin and spar thickness as design variables, not one or the other.')

            self.add_subsystem('wingbox_group',
                WingboxGroup(surface=surface),
                promotes_inputs=['mesh', 't_over_c'],
                promotes_outputs=['A', 'Iy', 'Iz', 'J', 'Qz', 'A_enc', 'A_int', 'htop', 'hbottom', 'hfront', 'hrear'] + wingbox_promotes)
        else:
            raise NameError('Please select a valid `fem_model_type` from either `tube` or `wingbox`.')

        if surface['fem_model_type'] == 'wingbox':
            promotes = ['A_int']
        else:
            promotes = []

        self.add_subsystem('struct_setup',
            SpatialBeamSetup(surface=surface),
            promotes_inputs=['mesh', 'A', 'Iy', 'Iz', 'J'] + promotes,
            promotes_outputs=['nodes', 'local_stiff_transformed', 'structural_mass', 'cg_location', 'element_mass'])
Exemplo n.º 2
0
    def setup(self):
        surface = self.options['surface']

        tube_promotes = []

        if 'thickness_cp' in surface.keys():
            tube_promotes.append('thickness_cp')

        self.add_subsystem('geometry',
            Geometry(surface=surface),
            promotes_inputs=[],
            promotes_outputs=['mesh'])

        if surface['fem_model_type'] == 'tube':
            self.add_subsystem('tube_group',
                TubeGroup(surface=surface),
                promotes_inputs=['mesh'],
                promotes_outputs=['A', 'Iy', 'Iz', 'J', 'radius', 'thickness'] + tube_promotes)
        elif surface['fem_model_type'] == 'wingbox':
            self.add_subsystem('wingbox_group',
                WingboxGroup(surface=surface),
                promotes_inputs=['mesh'],
                promotes_outputs=['A', 'Iy', 'Iz', 'J', 'radius', 'thickness'] + tube_promotes)
        else:
            raise NameError('Please select a valid `fem_model_type` from either `tube` or `wingbox`.')

        self.add_subsystem('struct_setup',
            SpatialBeamSetup(surface=surface),
            promotes_inputs=['mesh', 'A', 'Iy', 'Iz', 'J', 'load_factor'],
            promotes_outputs=['nodes', 'K', 'structural_weight', 'cg_location', 'element_weights'])

        self.add_subsystem('struct_states',
            SpatialBeamStates(surface=surface),
            promotes_inputs=['K', 'forces', 'loads', 'element_weights'],
            promotes_outputs=['disp'])

        self.add_subsystem('struct_funcs',
            SpatialBeamFunctionals(surface=surface),
            promotes_inputs=['thickness', 'radius', 'nodes', 'disp'],
            promotes_outputs=['thickness_intersects', 'vonmises', 'failure'])
Exemplo n.º 3
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 (NACA0015)
    'c_max_t': .303,  # chordwise location of maximum (NACA0015)
    # thickness
    'with_viscous': False,  # if true, compute viscous drag,
    'with_wave': False,
}  # end of surface dictionary

name = surface['name']

# Add geometry to the problem as the name of the surface.
# These groups are responsible for manipulating the geometry of the mesh,
# in this case spanwise twist.
geom_group = Geometry(surface=surface)
prob.model.add_subsystem(name, geom_group)

# Create the aero point group for this flight condition and add it to the model
aero_group = AeroPoint(surfaces=[surface], rotational=True)
point_name = 'aero_point_0'
prob.model.add_subsystem(point_name,
                         aero_group,
                         promotes_inputs=[
                             'v', 'alpha', 'beta', 'omega', 'Mach_number',
                             're', 'rho', 'cg'
                         ])

# Connect the mesh from the geometry component to the analysis point
prob.model.connect(name + '.mesh', point_name + '.' + name + '.def_mesh')
Exemplo n.º 4
0
def compute_drag_polar(Mach, alphas, surfaces, trimmed=False):

    if isinstance(surfaces, dict):
        surfaces = [
            surfaces,
        ]

    # Create the OpenMDAO problem
    prob = Problem()
    # Create an independent variable component that will supply the flow
    # conditions to the problem.
    indep_var_comp = IndepVarComp()
    indep_var_comp.add_output('v', val=248.136, units='m/s')
    indep_var_comp.add_output('alpha', val=0., units='deg')
    indep_var_comp.add_output('Mach_number', val=Mach)
    indep_var_comp.add_output('re', val=1.e6, units='1/m')
    indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
    indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')
    # Add this IndepVarComp to the problem model
    prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

    for surface in surfaces:
        name = surface['name']
        # Create and add a group that handles the geometry for the
        # aerodynamic lifting surface
        geom_group = Geometry(surface=surface)
        prob.model.add_subsystem(name, geom_group)

        # Connect the mesh from the geometry component to the analysis point
        prob.model.connect(name + '.mesh', 'aero.' + name + '.def_mesh')
        # Perform the connections with the modified names within the
        # 'aero_states' group.
        prob.model.connect(name + '.mesh',
                           'aero.aero_states.' + name + '_def_mesh')

    # Create the aero point group, which contains the actual aerodynamic
    # analyses
    point_name = 'aero'
    aero_group = AeroPoint(surfaces=surfaces)
    prob.model.add_subsystem(
        point_name,
        aero_group,
        promotes_inputs=['v', 'alpha', 'Mach_number', 're', 'rho', 'cg'])

    # For trimmed polar, setup balance component
    if trimmed == True:
        bal = BalanceComp()
        bal.add_balance(name='tail_rotation', rhs_val=0., units='deg')
        prob.model.add_subsystem('balance',
                                 bal,
                                 promotes_outputs=['tail_rotation'])
        prob.model.connect('aero.CM',
                           'balance.lhs:tail_rotation',
                           src_indices=[1])
        prob.model.connect('tail_rotation', 'tail.twist_cp')

        prob.model.nonlinear_solver = NonlinearBlockGS(use_aitken=True)

        prob.model.nonlinear_solver.options['iprint'] = 2
        prob.model.nonlinear_solver.options['maxiter'] = 100
        prob.model.linear_solver = DirectSolver()

    prob.setup()

    #prob['tail_rotation'] = -0.75

    prob.run_model()
    #prob.check_partials(compact_print = True)
    #prob.model.list_outputs(prom_name = True)

    prob.model.list_outputs(residuals=True)

    CLs = []
    CDs = []
    CMs = []

    for a in alphas:
        prob['alpha'] = a
        prob.run_model()
        CLs.append(prob['aero.CL'][0])
        CDs.append(prob['aero.CD'][0])
        CMs.append(prob['aero.CM'][1])  # Take only the longitudinal CM
        #print(a, prob['aero.CL'], prob['aero.CD'], prob['aero.CM'][1])

    # Plot CL vs alpha and drag polar
    fig, axes = plt.subplots(nrows=3)
    axes[0].plot(alphas, CLs)
    axes[1].plot(alphas, CMs)
    axes[2].plot(CLs, CDs)
    fig.savefig('drag_polar.pdf')
    #plt.show()

    return CLs, CDs, CMs
Exemplo n.º 5
0
    def test(self):

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 7,
            'num_x': 2,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 5
        }

        mesh, twist_cp = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'type': 'aero',
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type': 'tube',
            'twist_cp': twist_cp,
            'mesh': mesh,
            'num_x': mesh.shape[0],
            'num_y': mesh.shape[1],

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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.15,  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
        }

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 7,
            'num_x': 2,
            'wing_type': 'rect',
            'symmetry': True,
            'offset': np.array([50, 0., 0.])
        }

        mesh = generate_mesh(mesh_dict)

        surf_dict2 = {
            # Wing definition
            'name': 'tail',  # name of the surface
            'type': 'aero',
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'twist_cp': twist_cp,
            'mesh': mesh,
            'num_x': mesh.shape[0],
            'num_y': mesh.shape[1],

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.0,  # CD of the surface at alpha=0
            'fem_origin': 0.35,

            # Airfoil properties for viscous drag calculation
            'k_lam': 0.05,  # percentage of chord with laminar
            # flow, used for viscous drag
            't_over_c': 0.15,  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
        }

        surfaces = [surf_dict, surf_dict2]

        # Create the problem and the model group
        prob = Problem()

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5.)
        indep_var_comp.add_output('M', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

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

            geom_group = Geometry(surface=surface)

            # Add tmp_group to the problem as the name of the surface.
            # Note that is a group and performance group for each
            # individual surface.
            prob.model.add_subsystem(surface['name'], geom_group)

        # Loop through and add a certain number of aero points
        for i in range(1):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('M', point_name + '.M')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                name = surface['name']

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(name + '.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    name + '.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')

        # Set up the problem
        prob.setup()

        prob.run_model()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],
                         0.037210478659832125, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0],
                         0.5124736932248048, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][1],
                         -0.18108463722015625, 1e-6)
Exemplo n.º 6
0
    def setup(self):
        shape = self.options['shape']

        shape = (1, )
        self.add_subsystem('aerodynamics_geometry_group',
                           AerodynamicsGeometryGroup(shape=shape),
                           promotes=['*'])

        # indep_var_comp = om.IndepVarComp()
        # indep_var_comp.add_output('v', val=50, units='m/s')
        # indep_var_comp.add_output('Mach_number', val=0.3)
        # indep_var_comp.add_output('re', val=1.e5, units='1/m')
        # indep_var_comp.add_output('rho')
        # indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')
        # indep_var_comp.add_output('alpha', val = 2.)
        # indep_var_comp.add_output('beta', val = 0.)
        # indep_var_comp.add_output('xshear', val = np.zeros((9)))
        # indep_var_comp.add_output('yshear', val = np.zeros((9)))
        # indep_var_comp.add_output('zshear', val = np.zeros((9)))

        # self.add_subsystem('inputs_comp', indep_var_comp, promotes=['*'])

        mesh_dict = {
            'num_y': 17,
            'num_x': 9,
            'wing_type': 'rect',
            'symmetry': True,
            'chord': 0.1,
            'span': 1.,
            'xshear': 0.,
            'yshear': 0.,
            'zshear': 0.,
        }

        mesh = generate_mesh(mesh_dict)

        surface = {
            'name': 'wing',
            'symmetry': True,
            'S_ref_type': 'wetted',
            'twist_cp': np.array([-10., -3., 2.]),
            'mesh': mesh,
            'CL0': 0.0,
            'CD0': 0.001,
            'k_lam': 0.05,
            't_over_c_cp': np.array([0.1875]),
            'c_max_t': 0.1,
            'with_viscous': True,
            'with_wave': False,
            'sweep': 6.,
            'taper': 0.,
            'dihedral': 0.,
        }

        geom_group = Geometry(surface=surface)

        self.add_subsystem(surface['name'], geom_group)

        aero_group = AeroPoint(surfaces=[surface])
        point_name = 'aero_point'
        self.add_subsystem(point_name, aero_group)

        # Connect flow properties to the analysis point
        # # make connections in run file
        #self.connect('v', point_name + '.v')
        # self.connect('cruise_alpha', point_name + '.alpha') # made!
        # #self.connect('Mach_number', point_name + '.Mach_number')
        # self.connect('re', point_name + '.re')
        # #self.connect('rho', point_name + '.rho')
        # self.connect('cg', point_name + '.cg')

        # Connect the mesh from the geometry component to the analysis point
        self.connect('wing.mesh', 'aero_point.wing.def_mesh')

        # Perform the connections with the modified names within the 'aero_states' group.
        self.connect('wing.mesh', 'aero_point.aero_states.wing_def_mesh')
        self.connect('wing.t_over_c', 'aero_point.wing_perf.t_over_c')

        self.connect('wing_span', 'wing.mesh.stretch.span')
        self.connect('oas_wing_chord', 'wing.mesh.scale_x.chord')

        # group = CruiseAeroGroup(
        #     shape=shape
        # )
        # self.add_subsystem('cruise_aero_group', group, promotes=['*'])

        group = CruiseLiftDragGroup(shape=shape)
        self.add_subsystem('cruise_lift_drag_group', group, promotes=['*'])
Exemplo n.º 7
0
def compute_drag_polar_ground_effect(Mach,
                                     alphas,
                                     heights,
                                     surfaces,
                                     trimmed=False,
                                     visualize=False):
    if isinstance(surfaces, dict):
        surfaces = [
            surfaces,
        ]

    # Create the OpenMDAO problem
    prob = om.Problem()
    # Create an independent variable component that will supply the flow
    # conditions to the problem.
    indep_var_comp = om.IndepVarComp()
    indep_var_comp.add_output('v', val=248.136, units='m/s')
    indep_var_comp.add_output('alpha', val=0.0, units='deg')
    indep_var_comp.add_output('height_agl', val=8000, units='m')
    indep_var_comp.add_output('Mach_number', val=Mach)
    indep_var_comp.add_output('re', val=1.0e6, units='1/m')
    indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
    indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')
    # Add this IndepVarComp to the problem model
    prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

    for surface in surfaces:
        name = surface['name']
        # Create and add a group that handles the geometry for the
        # aerodynamic lifting surface
        geom_group = Geometry(surface=surface)
        prob.model.add_subsystem(name, geom_group)

        # Connect the mesh from the geometry component to the analysis point
        prob.model.connect(name + '.mesh', 'aero.' + name + '.def_mesh')
        # Perform the connections with the modified names within the
        # 'aero_states' group.
        prob.model.connect(name + '.mesh',
                           'aero.aero_states.' + name + '_def_mesh')

    # Create the aero point group, which contains the actual aerodynamic
    # analyses
    point_name = 'aero'
    aero_group = AeroPoint(surfaces=surfaces)
    prob.model.add_subsystem(point_name,
                             aero_group,
                             promotes_inputs=[
                                 'v', 'alpha', 'Mach_number', 're', 'rho',
                                 'cg', 'height_agl'
                             ])

    # For trimmed polar, setup balance component
    if trimmed == True:
        bal = om.BalanceComp()
        bal.add_balance(name='tail_rotation', rhs_val=0.0, units='deg')
        prob.model.add_subsystem('balance',
                                 bal,
                                 promotes_outputs=['tail_rotation'])
        prob.model.connect('aero.CM',
                           'balance.lhs:tail_rotation',
                           src_indices=[1])
        prob.model.connect('tail_rotation', 'tail.twist_cp')

        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)

        prob.model.nonlinear_solver.options['iprint'] = 2
        prob.model.nonlinear_solver.options['maxiter'] = 10
        prob.model.linear_solver = om.DirectSolver()
    if visualize:
        prob.driver = om.ScipyOptimizeDriver()
        prob.driver.options['tol'] = 1e-9
        recorder = om.SqliteRecorder("polar_ground_effect.db")
        prob.driver.add_recorder(recorder)
        prob.driver.recording_options['record_derivatives'] = True
        prob.driver.recording_options['includes'] = ['*']
        prob.driver.options['maxiter'] = 1
        # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('cg', lower=-0.0, upper=0.0)
        prob.model.add_objective('aero.CL', scaler=1e4)

    prob.setup()

    # prob['tail_rotation'] = -0.75
    span = prob['wing.mesh.stretch.span']

    prob.run_model()
    # prob.check_partials(compact_print = True)
    # prob.model.list_outputs(prom_name = True)

    prob.model.list_outputs(residuals=True)

    CLs = []
    CDs = []
    CMs = []
    for height in heights:
        CLs_h = []
        CDs_h = []
        CMs_h = []
        for a in alphas:
            prob['alpha'] = a
            prob['height_agl'] = height
            prob.run_model()
            CLs_h.append(prob['aero.CL'][0])
            CDs_h.append(prob['aero.CD'][0])
            CMs_h.append(prob['aero.CM'][1])  # Take only the longitudinal CM
            # print(a, prob['aero.CL'], prob['aero.CD'], prob['aero.CM'][1])
        CLs.append(CLs_h)
        CDs.append(CDs_h)
        CMs.append(CMs_h)
    # Plot the drag polar
    if visualize:
        prob.run_driver()
    fig, ax = plt.subplots(nrows=1)
    for ih, height in enumerate(heights):
        ax.plot(CLs[ih], CDs[ih], label='h/b=' + '%.1f' % (height / span)[0])
        ax.set_ylabel('CDi')
        ax.set_xlabel('CL')
    ax.legend()
    fig, ax = plt.subplots(nrows=1)
    # compute ground effect correction factor and plot
    CLs_arr = np.array(CLs)
    CDs_arr = np.array(CDs)
    k = CDs_arr[:, -1] / CLs_arr[:, -1]**2
    k = k / k[0]
    hob = np.array(heights) / span
    ax.plot(hob, k)
    ax.set_xscale('log')
    ax.set_xlabel('h/b')
    ax.set_ylabel('$C_{Di}/C_{Di,\infty}$')
    plt.show()
    return CLs, CDs, CMs
Exemplo n.º 8
0
    def test(self):
        import numpy as np

        import openmdao.api as om

        from openaerostruct.geometry.utils import generate_mesh
        from openaerostruct.geometry.geometry_group import Geometry
        from openaerostruct.aerodynamics.aero_groups import AeroPoint

        # Create a dictionary to store options about the mesh
        mesh_dict = {
            'num_y': 7,
            'num_x': 2,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 5
        }

        # Generate the aerodynamic mesh based on the previous dictionary
        mesh, twist_cp = generate_mesh(mesh_dict)

        # Create a dictionary with info and options about the aerodynamic
        # lifting surface
        surface = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type': 'tube',
            'twist_cp': twist_cp,
            'mesh': mesh,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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_cp':
            np.array([0.15]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
            'with_wave': False,  # if true, compute wave drag
        }

        # Create the OpenMDAO problem
        prob = om.Problem()

        # Create an independent variable component that will supply the flow
        # conditions to the problem.
        indep_var_comp = om.IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5., units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        # Add this IndepVarComp to the problem model
        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

        # Create and add a group that handles the geometry for the
        # aerodynamic lifting surface
        geom_group = Geometry(surface=surface)
        prob.model.add_subsystem(surface['name'], geom_group)

        # Create the aero point group, which contains the actual aerodynamic
        # analyses
        aero_group = AeroPoint(surfaces=[surface])
        point_name = 'aero_point_0'
        prob.model.add_subsystem(
            point_name,
            aero_group,
            promotes_inputs=['v', 'alpha', 'Mach_number', 're', 'rho', 'cg'])

        name = surface['name']

        # Connect the mesh from the geometry component to the analysis point
        prob.model.connect(name + '.mesh',
                           point_name + '.' + name + '.def_mesh')

        # Perform the connections with the modified names within the
        # 'aero_states' group.
        prob.model.connect(name + '.mesh',
                           point_name + '.aero_states.' + name + '_def_mesh')

        prob.model.connect(name + '.t_over_c',
                           point_name + '.' + name + '_perf.' + 't_over_c')

        # Import the Scipy Optimizer and set the driver of the problem to use
        # it, which defaults to an SLSQP optimization method
        prob.driver = om.ScipyOptimizeDriver()
        prob.driver.options['tol'] = 1e-9

        recorder = om.SqliteRecorder("aero.db")
        prob.driver.add_recorder(recorder)
        prob.driver.recording_options['record_derivatives'] = True
        prob.driver.recording_options['includes'] = ['*']

        # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('wing.twist_cp', lower=-10., upper=15.)
        prob.model.add_constraint(point_name + '.wing_perf.CL', equals=0.5)
        prob.model.add_objective(point_name + '.wing_perf.CD', scaler=1e4)

        # Set up and run the optimization problem
        prob.setup()
        # prob.check_partials(compact_print=True)
        # exit()
        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],
                         0.033389699871650073, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.5, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][1], -1.7885550372372376,
                         1e-6)
    def test(self):

        from openaerostruct.geometry.utils import generate_mesh, write_FFD_file
        from openaerostruct.geometry.geometry_group import Geometry
        from openaerostruct.aerodynamics.aero_groups import AeroPoint
        from openaerostruct.integration.multipoint_comps import MultiCD

        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_check_partials
        from pygeo import DVGeometry

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 5,
            'num_x': 3,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 5,
            'span_cos_spacing': 0.0,
        }

        mesh, _ = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type': 'tube',
            'mesh': mesh,
            'mx': 2,
            'my': 3,
            'geom_manipulator': 'FFD',
            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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_cp':
            np.array([0.15]),  # thickness over chord ratio (NACA0015)
            'c_max_t': 0.303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
            'with_wave': False,  # if true, compute wave drag
        }

        surfaces = [surf_dict]

        n_points = 2

        # Create the problem and the model group
        prob = om.Problem()

        indep_var_comp = om.IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha',
                                  val=np.ones(n_points) * 6.64,
                                  units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.0e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

        # Loop over each surface in the surfaces list
        for surface in surfaces:
            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']

            # FFD setup
            filename = write_FFD_file(surface, surface['mx'], surface['my'])
            DVGeo = DVGeometry(filename)
            geom_group = Geometry(surface=surface, DVGeo=DVGeo)

            # Add tmp_group to the problem with the name of the surface.
            prob.model.add_subsystem(name + '_geom', geom_group)

        # Loop through and add a certain number of aero points
        for i in range(n_points):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha', src_indices=[i])
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:
                name = surface['name']

                # Connect the drag coeff at this point to the multi_CD component, which does the summation.
                prob.model.connect(point_name + '.CD',
                                   'multi_CD.' + str(i) + '_CD')

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(name + '_geom.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    name + '_geom.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')
                prob.model.connect(
                    name + '_geom.t_over_c',
                    point_name + '.' + name + '_perf.' + 't_over_c')

        prob.model.add_subsystem('multi_CD',
                                 MultiCD(n_points=n_points),
                                 promotes_outputs=['CD'])

        prob.driver = om.ScipyOptimizeDriver()

        # Setup problem and add design variables, constraint, and objective
        # design variable is the wing shape, and angle-of-attack at each point.
        prob.model.add_design_var('alpha', lower=-15, upper=15)
        prob.model.add_design_var('wing_geom.shape', lower=-3, upper=2)

        # set different target CL value at each point.
        prob.model.add_constraint('aero_point_0.wing_perf.CL', equals=0.45)
        prob.model.add_constraint('aero_point_1.wing_perf.CL', equals=0.5)

        # objective is the sum of CDs at each point.
        prob.model.add_objective('CD', scaler=1e4)

        # Set up the problem
        prob.setup()
        prob.run_model()

        # Check the partials at this point in the design space
        data = prob.check_partials(compact_print=True,
                                   out_stream=None,
                                   method='fd',
                                   step=1e-5)
        assert_check_partials(data, atol=1e20, rtol=1e-3)
Exemplo n.º 10
0
    def test(self):
        import numpy as np
        from openaerostruct.geometry.utils import generate_mesh, write_FFD_file
        from openaerostruct.geometry.geometry_group import Geometry
        from openaerostruct.transfer.displacement_transfer import DisplacementTransfer

        from openaerostruct.aerodynamics.aero_groups import AeroPoint
        from openaerostruct.integration.multipoint_comps import MultiCD

        import openmdao.api as om

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 5,
            'num_x': 3,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 5,
            'span_cos_spacing': 0.
        }

        mesh, twist_cp = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type': 'tube',
            'mesh': mesh,
            'twist_cp': twist_cp,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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_cp':
            np.array([0.15]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
            'with_wave': False,  # if true, compute wave drag
        }

        surfaces = [surf_dict]

        n_points = 2

        # Create the problem and the model group
        prob = om.Problem()

        indep_var_comp = om.IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha',
                                  val=np.ones(n_points) * 6.64,
                                  units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

        # Loop through and add a certain number of aero points
        for i in range(n_points):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha', src_indices=[i])
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                geom_group = Geometry(surface=surface)

                # Add tmp_group to the problem as the name of the surface.
                # Note that is a group and performance group for each
                # individual surface.
                aero_group.add_subsystem(surface['name'] + '_geom', geom_group)

                name = surface['name']
                prob.model.connect(point_name + '.CD',
                                   'multi_CD.' + str(i) + '_CD')

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(point_name + '.' + name + '_geom.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    point_name + '.' + name + '_geom.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')

                prob.model.connect(
                    point_name + '.' + name + '_geom.t_over_c',
                    point_name + '.' + name + '_perf.' + 't_over_c')

        prob.model.add_subsystem('multi_CD',
                                 MultiCD(n_points=n_points),
                                 promotes_outputs=['CD'])

        prob.driver = om.ScipyOptimizeDriver()
        prob.driver.options['tol'] = 1e-9

        # # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('alpha', lower=-15, upper=15)

        prob.model.add_design_var('aero_point_0.wing_geom.twist_cp',
                                  lower=-5,
                                  upper=8)
        prob.model.add_constraint('aero_point_0.wing_perf.CL', equals=0.45)

        prob.model.add_design_var('aero_point_1.wing_geom.twist_cp',
                                  lower=-5,
                                  upper=8)
        prob.model.add_constraint('aero_point_1.wing_perf.CL', equals=0.5)

        prob.model.add_objective('CD', scaler=1e4)

        # Set up the problem
        prob.setup()

        # print('gona check')
        # prob.run_model()
        # prob.check_partials(compact_print=True)
        # exit()
        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.45,
                         1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],
                         0.03231556149303963, 1e-6)
        assert_rel_error(self, prob['aero_point_1.wing_perf.CL'][0], 0.5, 1e-6)
        assert_rel_error(self, prob['aero_point_1.wing_perf.CD'][0],
                         0.03376555561457066, 1e-6)
Exemplo n.º 11
0
    def test(self):

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 7,
            'num_x': 3,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 5
        }

        mesh, twist_cp = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type': 'tube',
            'twist_cp': twist_cp,
            'mesh': mesh,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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_cp':
            np.array([0.15]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
            'with_wave': False,  # if true, compute wave drag
        }

        surfaces = [surf_dict]

        # Create the problem and the model group
        prob = om.Problem()

        indep_var_comp = om.IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5., units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

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

            geom_group = Geometry(surface=surface)

            # Add tmp_group to the problem as the name of the surface.
            # Note that is a group and performance group for each
            # individual surface.
            prob.model.add_subsystem(surface['name'], geom_group)

        # Loop through and add a certain number of aero points
        for i in range(1):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                name = surface['name']

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(name + '.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    name + '.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')

                prob.model.connect(
                    name + '.t_over_c',
                    point_name + '.' + name + '_perf.' + 't_over_c')

        recorder = om.SqliteRecorder("aero_analysis.db")
        prob.driver.add_recorder(recorder)
        prob.driver.recording_options['record_derivatives'] = True
        prob.driver.recording_options['includes'] = ['*']

        # Set up the problem
        prob.setup()

        # om.view_model(prob)

        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],
                         0.038041969673747206, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0],
                         0.5112640267782032, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][1], -1.735548800386354,
                         1e-6)
Exemplo n.º 12
0
def run_OAS(inputs,
            with_viscous=True,
            with_wave=True,
            t_over_c=np.array([0.12])):
    # Create a dictionary with info and options about the aerodynamic
    # lifting surface
    surface = {
        # Wing definition
        "name": "wing",  # name of the surface
        "symmetry": True,  # if true, model one half of wing
        # reflected across the plane y = 0
        "S_ref_type": "projected",  # how we compute the wing area,
        # can be 'wetted' or 'projected'
        "twist_cp": inputs["twist"],
        "mesh": inputs["mesh"],
        # Aerodynamic performance of the lifting surface at
        # an angle of attack of 0 (alpha=0).
        # These CL0 and CD0 values are added to the CL and CD
        # obtained from aerodynamic analysis of the surface to get
        # the total CL and CD.
        # These CL0 and CD0 values do not vary wrt alpha.
        "CL0": 0.0,  # CL of the surface at alpha=0
        "CD0": 0.0,  # CD of the surface at 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_cp": t_over_c,  # thickness over chord ratio (NACA0015)
        "c_max_t": 0.37,  # chordwise location of maximum (NACA0015)
        # thickness
        "with_viscous": with_viscous,  # if true, compute viscous drag
        "with_wave": with_wave,  # if true, compute wave drag
    }

    # Create the OpenMDAO problem
    prob = om.Problem()

    # Create an independent variable component that will supply the flow
    # conditions to the problem.
    indep_var_comp = om.IndepVarComp()
    indep_var_comp.add_output("v", val=inputs["v"], units="m/s")
    indep_var_comp.add_output("alpha", val=inputs["alpha"], units="deg")
    indep_var_comp.add_output("Mach_number", val=inputs["Mach_number"])
    indep_var_comp.add_output("re", val=inputs["re"], units="1/m")
    indep_var_comp.add_output("rho", val=inputs["rho"], units="kg/m**3")
    indep_var_comp.add_output("cg", val=np.zeros((3)), units="m")

    # Add this IndepVarComp to the problem model
    prob.model.add_subsystem("prob_vars", indep_var_comp, promotes=["*"])

    # Create and add a group that handles the geometry for the
    # aerodynamic lifting surface
    geom_group = Geometry(surface=surface)
    prob.model.add_subsystem(surface["name"], geom_group)

    # Create the aero point group, which contains the actual aerodynamic
    # analyses
    aero_group = AeroPoint(surfaces=[surface])
    point_name = "aero_point_0"
    prob.model.add_subsystem(
        point_name,
        aero_group,
        promotes_inputs=["v", "alpha", "Mach_number", "re", "rho", "cg"])

    name = surface["name"]

    # Connect the mesh from the geometry component to the analysis point
    prob.model.connect(name + ".mesh", point_name + "." + name + ".def_mesh")

    # Perform the connections with the modified names within the
    # 'aero_states' group.
    prob.model.connect(name + ".mesh",
                       point_name + ".aero_states." + name + "_def_mesh")
    prob.model.connect(name + ".t_over_c",
                       point_name + "." + name + "_perf." + "t_over_c")

    # Set up and run the model
    prob.setup()
    prob.run_model()
    outputs = {}
    outputs["CL"] = prob["aero_point_0.wing_perf.CL"]
    outputs["CD"] = prob["aero_point_0.wing_perf.CD"]
    return outputs
Exemplo n.º 13
0
    def test(self):

        from openaerostruct.geometry.utils import generate_mesh, write_FFD_file
        from openaerostruct.geometry.geometry_group import Geometry
        from openaerostruct.transfer.displacement_transfer import DisplacementTransfer

        from openaerostruct.aerodynamics.aero_groups import AeroPoint
        from openaerostruct.integration.multipoint_comps import MultiCD, GeomMatch

        from openmdao.api import IndepVarComp, Problem, Group, NewtonSolver, ScipyIterativeSolver, LinearBlockGS, NonlinearBlockGS, DirectSolver, LinearBlockGS, PetscKSP, ScipyOptimizeDriver, ExplicitComponent# TODO, SqliteRecorder, CaseReader, profile
        from openmdao.devtools import iprofile
        from openmdao.api import view_model
        from pygeo import DVGeometry

        # Create a dictionary to store options about the surface
        mesh_dict = {'num_y' : 5,
                     'num_x' : 3,
                     'wing_type' : 'CRM',
                     'symmetry' : True,
                     'num_twist_cp' : 5,
                     'span_cos_spacing' : 0.}

        mesh, _ = generate_mesh(mesh_dict)

        surf_dict = {
                    # Wing definition
                    'name' : 'wing',        # name of the surface
                    'type' : 'aero',
                    'symmetry' : True,     # if true, model one half of wing
                                            # reflected across the plane y = 0
                    'S_ref_type' : 'wetted', # how we compute the wing area,
                                             # can be 'wetted' or 'projected'
                    'fem_model_type' : 'tube',

                    'mesh' : mesh,
                    'mx' : 2,
                    'my' : 3,
                    'geom_manipulator' : 'FFD',

                    # Aerodynamic performance of the lifting surface at
                    # an angle of attack of 0 (alpha=0).
                    # These CL0 and CD0 values are added to the CL and CD
                    # obtained from aerodynamic analysis of the surface to get
                    # the total CL and CD.
                    # These CL0 and CD0 values do not vary wrt alpha.
                    'CL0' : 0.0,            # CL of the surface at alpha=0
                    'CD0' : 0.015,            # CD of the surface at 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.15,      # thickness over chord ratio (NACA0015)
                    'c_max_t' : .303,       # chordwise location of maximum (NACA0015)
                                            # thickness
                    'with_viscous' : True,  # if true, compute viscous drag
                    }

        surf_dict['num_x'], surf_dict['num_y'] = surf_dict['mesh'].shape[:2]

        surfaces = [surf_dict]

        n_points = 2

        # Create the problem and the model group
        prob = Problem()

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=np.ones(n_points)*6.64)
        indep_var_comp.add_output('M', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars',
            indep_var_comp,
            promotes=['*'])


        # Loop through and add a certain number of aero points
        for i in range(n_points):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha', src_indices=[i])
            prob.model.connect('M', point_name + '.M')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                filename = write_FFD_file(surface, surface['mx'], surface['my'])
                DVGeo = DVGeometry(filename)
                geom_group = Geometry(surface=surface, DVGeo=DVGeo)

                # Add tmp_group to the problem as the name of the surface.
                # Note that is a group and performance group for each
                # individual surface.
                aero_group.add_subsystem(surface['name'] + '_geom', geom_group)

                name = surface['name']
                prob.model.connect(point_name + '.CD', 'multi_CD.' + str(i) + '_CD')
                prob.model.connect(point_name + '.wing_geom.shape', 'geom_match.' + str(i) + '_shape')

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(point_name + '.' + name + '_geom.mesh', point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(point_name + '.' + name + '_geom.mesh', point_name + '.aero_states.' + name + '_def_mesh')

        prob.model.add_subsystem('multi_CD', MultiCD(n_points=n_points), promotes_outputs=['CD'])
        prob.model.add_subsystem('geom_match', GeomMatch(n_points=n_points, mx=surf_dict['mx'], my=surf_dict['my']), promotes_outputs=['shape_diff'])

        from openmdao.api import pyOptSparseDriver
        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = "SNOPT"
        prob.driver.opt_settings = {'Major optimality tolerance': 1.0e-5,
                                    'Major feasibility tolerance': 1.0e-5}

        # # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('alpha', lower=-15, upper=15)

        prob.model.add_design_var('aero_point_0.wing_geom.shape', lower=-3, upper=2)
        prob.model.add_constraint('aero_point_0.wing_perf.CL', equals=0.45)

        prob.model.add_design_var('aero_point_1.wing_geom.shape', lower=-3, upper=2)
        prob.model.add_constraint('aero_point_1.wing_perf.CL', equals=0.5)

        prob.model.add_constraint('shape_diff', equals=0., indices=range(surf_dict['my'] * (n_points - 1) * 1), linear=True)
        # prob.model.add_constraint('shape_diff', equals=0., linear=True)

        prob.model.add_objective('CD', scaler=1e4)

        # Set up the problem
        prob.setup()

        # prob.run_model()
        prob.run_driver()

        # prob.check_partials(compact_print=True)

        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.45, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0], 0.03229527496681374, 1e-6)
        assert_rel_error(self, prob['aero_point_1.wing_perf.CL'][0], 0.5, 1e-6)
        assert_rel_error(self, prob['aero_point_1.wing_perf.CD'][0], 0.033767398588947985, 1e-6)
    def test(self):

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 5,
            'num_x': 3,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 5,
            'span_cos_spacing': 0.
        }

        mesh, twist_cp = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type': 'tube',
            'mesh': mesh,
            'twist_cp': twist_cp,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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_cp':
            np.array([0.15]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
            'with_wave': False,  # if true, compute wave drag
            'span': 10.
        }

        surfaces = [surf_dict]

        n_points = 2

        # Create the problem and the model group
        prob = Problem()

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=6.64, units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('t_over_c_cp', val=np.array([0.15]))
        indep_var_comp.add_output('span', val=12., units='m')
        indep_var_comp.add_output('twist_cp_0', val=np.zeros((5)), units='deg')
        indep_var_comp.add_output('twist_cp_1', val=np.zeros((5)), units='deg')

        prob.model.add_subsystem('geom_vars', indep_var_comp, promotes=['*'])

        # Loop through and add a certain number of aero points
        for i in range(n_points):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                geom_group = Geometry(surface=surface, connect_geom_DVs=False)

                # Add tmp_group to the problem as the name of the surface.
                # Note that is a group and performance group for each
                # individual surface.
                aero_group.add_subsystem(surface['name'] + '_geom', geom_group)

                name = surface['name']
                prob.model.connect(point_name + '.CD',
                                   'multi_CD.' + str(i) + '_CD')

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(point_name + '.' + name + '_geom.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    point_name + '.' + name + '_geom.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')

                prob.model.connect(
                    point_name + '.' + name + '_geom.t_over_c',
                    point_name + '.' + name + '_perf.' + 't_over_c')

                # prob.model.connect(point_name + '.' + name + '_geom.span', 'span_diff_comp.span_' + str(i))

        # Connect geometric design variables to each point
        prob.model.connect('t_over_c_cp', 'aero_point_0.wing_geom.t_over_c_cp')
        prob.model.connect('t_over_c_cp', 'aero_point_1.wing_geom.t_over_c_cp')

        prob.model.connect('span', 'aero_point_0.wing_geom.span')
        prob.model.connect('span', 'aero_point_1.wing_geom.span')

        prob.model.connect('twist_cp_0', 'aero_point_0.wing_geom.twist_cp')
        prob.model.connect('twist_cp_1', 'aero_point_1.wing_geom.twist_cp')

        prob.model.add_subsystem('multi_CD',
                                 MultiCD(n_points=n_points),
                                 promotes_outputs=['CD'])

        from openmdao.api import ScipyOptimizeDriver
        prob.driver = ScipyOptimizeDriver()
        prob.driver.options['tol'] = 1e-9

        # # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('alpha', lower=-15, upper=15)

        prob.model.add_design_var('twist_cp_0', lower=-5, upper=8)
        prob.model.add_design_var('twist_cp_1', lower=-5, upper=8)

        prob.model.add_design_var('span', lower=2, upper=15)

        prob.model.add_constraint('aero_point_0.wing_perf.CL', equals=0.45)
        prob.model.add_constraint('aero_point_1.wing_perf.CL', equals=0.50)

        prob.model.add_objective('CD', scaler=1e4)

        # Set up the problem
        prob.setup()

        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.45,
                         1e-6)
        assert_rel_error(self, prob['aero_point_1.wing_perf.CL'][0], 0.5, 1e-6)
        assert_rel_error(
            self, prob['twist_cp_0'],
            np.array([8., -1.21207749, -2.42415497, -1.21207749, -1.0821358]),
            1e-6)
        assert_rel_error(
            self, prob['twist_cp_1'],
            np.array([8., -0.02049115, -0.0409823, -0.02049115, 0.77903674]),
            1e-6)
        assert_rel_error(self, prob['aero_point_1.wing_perf.CL'][0], 0.5, 1e-6)
    def __init__(self):
        # Create a dictionary to store options about the mesh
        mesh_dict = {'num_y' : 7,
                     'num_x' : 2,
                     'wing_type' : 'CRM',
                     'symmetry' : True,
                     'num_twist_cp' : 5}

        # Generate the aerodynamic mesh based on the previous dictionary
        mesh, twist_cp = generate_mesh(mesh_dict)

        # Create a dictionary with info and options about the aerodynamic
        # lifting surface
        surface = {
                    # Wing definition
                    'name' : 'wing',        # name of the surface
                    'type' : 'aero',
                    'symmetry' : True,     # if true, model one half of wing
                                            # reflected across the plane y = 0
                    'S_ref_type' : 'wetted', # how we compute the wing area,
                                             # can be 'wetted' or 'projected'
                    'fem_model_type' : 'tube',

                    'twist_cp' : twist_cp,
                    'mesh' : mesh,
                    'num_x' : mesh.shape[0],
                    'num_y' : mesh.shape[1],

                    # Aerodynamic performance of the lifting surface at
                    # an angle of attack of 0 (alpha=0).
                    # These CL0 and CD0 values are added to the CL and CD
                    # obtained from aerodynamic analysis of the surface to get
                    # the total CL and CD.
                    # These CL0 and CD0 values do not vary wrt alpha.
                    'CL0' : 0.0,            # CL of the surface at alpha=0
                    'CD0' : 0.015,            # CD of the surface at 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_cp' : np.array([0.15]),      # thickness over chord ratio (NACA0015)
                    'c_max_t' : .303,       # chordwise location of maximum (NACA0015)
                                            # thickness
                    'with_viscous' : True,  # if true, compute viscous drag
                    'with_wave' : False,     # if true, compute wave drag
                    }

        # Create the OpenMDAO problem
        self.prob = Problem()

        # Create an independent variable component that will supply the flow
        # conditions to the problem.
        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5., units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        # Add this IndepVarComp to the problem model
        self.prob.model.add_subsystem('prob_vars',
            indep_var_comp,
            promotes=['*'])

        # Create and add a group that handles the geometry for the
        # aerodynamic lifting surface
        geom_group = Geometry(surface=surface)
        self.prob.model.add_subsystem(surface['name'], geom_group)

        # Create the aero point group, which contains the actual aerodynamic
        # analyses
        aero_group = AeroPoint(surfaces=[surface])
        point_name = 'aero_point_0'
        self.prob.model.add_subsystem(point_name, aero_group,
            promotes_inputs=['v', 'alpha', 'Mach_number', 're', 'rho', 'cg'])

        name = surface['name']

        # Connect the mesh from the geometry component to the analysis point
        self.prob.model.connect(name + '.mesh', point_name + '.' + name + '.def_mesh')

        # Perform the connections with the modified names within the
        # 'aero_states' group.
        self.prob.model.connect(name + '.mesh', point_name + '.aero_states.' + name + '_def_mesh')
        self.prob.model.connect(name + '.t_over_c', point_name + '.' + name + '_perf.' + 't_over_c')
        self.prob.setup()
    def test(self):

        from openaerostruct.geometry.utils import generate_mesh, write_FFD_file
        from openaerostruct.geometry.geometry_group import Geometry
        from openaerostruct.transfer.displacement_transfer import DisplacementTransfer

        from openaerostruct.aerodynamics.aero_groups import AeroPoint

        from openmdao.api import IndepVarComp, Problem, Group, NewtonSolver, ScipyIterativeSolver, LinearBlockGS, NonlinearBlockGS, DirectSolver, LinearBlockGS, PetscKSP, ScipyOptimizeDriver# TODO, SqliteRecorder, CaseReader, profile
        from openmdao.devtools import iprofile
        from openmdao.api import view_model
        from six import iteritems
        from pygeo import DVGeometry

        # Create a dictionary to store options about the surface
        mesh_dict = {'num_y' : 7,
                     'num_x' : 3,
                     'wing_type' : 'CRM',
                     'symmetry' : True,
                     'num_twist_cp' : 5,
                     'span_cos_spacing' : 0.}

        mesh, _ = generate_mesh(mesh_dict)

        surf_dict = {
                    # Wing definition
                    'name' : 'wing',        # name of the surface
                    'symmetry' : True,     # if true, model one half of wing
                                            # reflected across the plane y = 0
                    'S_ref_type' : 'wetted', # how we compute the wing area,
                                             # can be 'wetted' or 'projected'
                    'fem_model_type' : 'tube',

                    'DVGeo' : True,
                    'mesh' : mesh,
                    'mx' : 2,
                    'my' : 3,

                    # Aerodynamic performance of the lifting surface at
                    # an angle of attack of 0 (alpha=0).
                    # These CL0 and CD0 values are added to the CL and CD
                    # obtained from aerodynamic analysis of the surface to get
                    # the total CL and CD.
                    # These CL0 and CD0 values do not vary wrt alpha.
                    'CL0' : 0.0,            # CL of the surface at alpha=0
                    'CD0' : 0.015,            # CD of the surface at 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_cp' : np.array([0.15]),      # thickness over chord ratio (NACA0015)
                    'c_max_t' : .303,       # chordwise location of maximum (NACA0015)
                                            # thickness
                    'with_viscous' : True,  # if true, compute viscous drag
                    'with_wave' : False,     # if true, compute wave drag
                    }

        surfaces = [surf_dict]

        # Create the problem and the model group
        prob = Problem()

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=6.64, units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars',
            indep_var_comp,
            promotes=['*'])

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

            filename = write_FFD_file(surface, surface['mx'], surface['my'])
            DVGeo = DVGeometry(filename)
            geom_group = Geometry(surface=surface, DVGeo=DVGeo)

            # Add tmp_group to the problem as the name of the surface.
            # Note that is a group and performance group for each
            # individual surface.
            prob.model.add_subsystem(surface['name'], geom_group)

        # Loop through and add a certain number of aero points
        for i in range(1):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                name = surface['name']

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(name + '.mesh', point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(name + '.mesh', point_name + '.aero_states.' + name + '_def_mesh')

                prob.model.connect(name + '.t_over_c', point_name + '.' + name + '_perf.' + 't_over_c')

        from openmdao.api import pyOptSparseDriver
        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = "SNOPT"
        prob.driver.opt_settings = {'Major optimality tolerance': 1.0e-6,
                                    'Major feasibility tolerance': 1.0e-6}

        # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('alpha', lower=-15, upper=15)
        prob.model.add_design_var('wing.shape', lower=-3, upper=2)

        # prob.model.add_constraint('wing.shape', equals=0., indices=range(surf_dict['my'] * 2), linear=True)
        prob.model.add_constraint(point_name + '.wing_perf.CL', equals=0.5)
        prob.model.add_objective(point_name + '.wing_perf.CD', scaler=1e4)

        # Set up the problem
        prob.setup()

        # view_model(prob, outfile='aero.html', show_browser=False)

        # prob.run_model()
        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0], 0.03398038, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.5, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][1], -1.7736315914915437, 1e-5)
Exemplo n.º 17
0
    def test(self):

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 11,
            'num_x': 3,
            'wing_type': 'CRM',
            'symmetry': False,
            'num_twist_cp': 5
        }

        mesh, twist_cp = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'type': 'aero',
            'symmetry': False,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'mesh': mesh,
            'num_x': mesh.shape[0],
            'num_y': mesh.shape[1],
            'twist_cp': twist_cp,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.0,  # CD of the surface at 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_cp':
            np.array([0.10, 0.15,
                      0.2]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,  # if true, compute viscous drag
            'with_wave': True,  # if true, compute wave drag
        }

        surfaces = [surf_dict]

        # Create the problem and the model group
        prob = Problem()

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5., units='deg')
        indep_var_comp.add_output('M', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

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

            geom_group = Geometry(surface=surface)

            # Add tmp_group to the problem as the name of the surface.
            # Note that is a group and performance group for each
            # individual surface.
            prob.model.add_subsystem(surface['name'], geom_group)

        # Loop through and add a certain number of aero points
        for i in range(1):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('M', point_name + '.M')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                name = surface['name']

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(name + '.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    name + '.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')

                prob.model.connect(
                    name + '.t_over_c',
                    point_name + '.' + name + '_perf.' + 't_over_c')

        from openmdao.api import ScipyOptimizeDriver
        prob.driver = ScipyOptimizeDriver()
        prob.driver.options['tol'] = 1e-9

        recorder = SqliteRecorder("aero_opt_wavedrag.db")
        prob.driver.add_recorder(recorder)
        prob.driver.recording_options['record_derivatives'] = True

        # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('wing.twist_cp', lower=-10., upper=15.)
        prob.model.add_constraint(point_name + '.wing_perf.CL', equals=0.5)
        prob.model.add_objective(point_name + '.wing_perf.CD', scaler=1e4)

        # Set up the problem
        prob.setup()

        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0], 0.5, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],
                         0.022662637, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][1], -0.179451279, 1e-6)
Exemplo n.º 18
0
    def test(self):
        import numpy as np

        from openaerostruct.geometry.utils import generate_mesh
        from openaerostruct.geometry.geometry_group import Geometry
        from openaerostruct.aerodynamics.aero_groups import AeroPoint

        from openmdao.api import IndepVarComp, Problem, Group

        # Instantiate the problem and the model group
        prob = Problem()

        indep_var_comp = IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5., units='deg')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 5,
            'num_x': 3,
            'wing_type': 'rect',
            'symmetry': True,
            'span': 10.,
            'chord': 1,
            'span_cos_spacing': 1.
        }

        mesh = generate_mesh(mesh_dict)

        surface = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'symmetry': True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'twist_cp': np.zeros(2),
            'mesh': mesh,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.0,  # CD of the surface at 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_cp':
            np.array([0.12]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': False,  # if true, compute viscous drag,
            'with_wave': False,  # if true, compute wave drag
            'sweep': 0.,
            'dihedral': 0.,
            'taper': 1.,
        }  # end of surface dictionary

        geom_group = Geometry(surface=surface)

        # Add tmp_group to the problem as the name of the surface.
        # Note that is a group and performance group for each
        # individual surface.
        prob.model.add_subsystem(surface['name'], geom_group)

        # Create the aero point group and add it to the model
        aero_group = AeroPoint(surfaces=[surface])
        point_name = 'aero_point_0'
        prob.model.add_subsystem(point_name, aero_group)

        # Connect flow properties to the analysis point
        prob.model.connect('v', point_name + '.v')
        prob.model.connect('alpha', point_name + '.alpha')
        prob.model.connect('Mach_number', point_name + '.Mach_number')
        prob.model.connect('re', point_name + '.re')
        prob.model.connect('rho', point_name + '.rho')
        prob.model.connect('cg', point_name + '.cg')

        name = 'wing'

        # Connect the mesh from the geometry component to the analysis point
        prob.model.connect(name + '.mesh', point_name + '.' + \
            name + '.def_mesh')

        # Perform the connections with the modified names within the
        # 'aero_states' group.
        prob.model.connect(name + '.mesh', point_name + \
            '.aero_states.' + name + '_def_mesh')

        prob.model.connect(name + '.t_over_c',
                           point_name + '.' + name + '_perf.' + 't_over_c')

        from openmdao.api import ScipyOptimizeDriver
        prob.driver = ScipyOptimizeDriver()

        # # Setup problem and add design variables, constraint, and objective
        prob.model.add_design_var('wing.twist_cp', lower=-10., upper=15.)
        prob.model.add_design_var('wing.sweep', lower=-10., upper=30.)
        prob.model.add_design_var('wing.dihedral', lower=-10., upper=15.)
        prob.model.add_constraint(point_name + '.wing_perf.CL', equals=0.5)
        prob.model.add_objective(point_name + '.wing_perf.CD', scaler=1e4)

        # Set up the problem
        prob.setup()

        prob.run_driver()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],\
            0.0049392534859265614, 1e-6)
Exemplo n.º 19
0
    def setup(self):
        surface = self.options['surface']

        tube_promotes = []
        tube_inputs = []

        if 'thickness_cp' in surface.keys():
            tube_promotes.append('thickness_cp')
        if 'radius_cp' not in surface.keys():
            tube_inputs = ['mesh', 't_over_c']

        self.add_subsystem('geometry',
            Geometry(surface=surface),
            promotes_inputs=[],
            promotes_outputs=['mesh', 't_over_c'])

        if surface['fem_model_type'] == 'tube':
            self.add_subsystem('tube_group',
                TubeGroup(surface=surface),
                promotes_inputs=tube_inputs,
                promotes_outputs=['A', 'Iy', 'Iz', 'J', 'radius', 'thickness'] + tube_promotes)
        elif surface['fem_model_type'] == 'wingbox':
            wingbox_promotes = []
            if 'skin_thickness_cp' in surface.keys() and 'spar_thickness_cp' in surface.keys():
                wingbox_promotes.append('skin_thickness_cp')
                wingbox_promotes.append('spar_thickness_cp')
                wingbox_promotes.append('skin_thickness')
                wingbox_promotes.append('spar_thickness')
            elif 'skin_thickness_cp' in surface.keys() or 'spar_thickness_cp' in surface.keys():
                raise NameError('Please have both skin and spar thickness as design variables, not one or the other.')

            self.add_subsystem('wingbox_group',
                WingboxGroup(surface=surface),
                promotes_inputs=['mesh', 't_over_c'],
                promotes_outputs=['A', 'Iy', 'Iz', 'J', 'Qz', 'A_enc', 'A_int', 'htop', 'hbottom', 'hfront', 'hrear'] + wingbox_promotes)
        else:
            raise NameError('Please select a valid `fem_model_type` from either `tube` or `wingbox`.')

        if surface['fem_model_type'] == 'tube':
            self.add_subsystem('struct_setup',
                SpatialBeamSetup(surface=surface),
                promotes_inputs=['mesh', 'A', 'Iy', 'Iz', 'J'],
                promotes_outputs=['nodes', 'local_stiff_transformed', 'structural_mass', 'cg_location', 'element_mass'])
        else:
            self.add_subsystem('struct_setup',
                SpatialBeamSetup(surface=surface),
                promotes_inputs=['mesh', 'A', 'Iy', 'Iz', 'J', 'A_int'],
                promotes_outputs=['nodes', 'local_stiff_transformed', 'structural_mass', 'cg_location', 'element_mass', ])

        promotes = []
        if surface['struct_weight_relief']:
            promotes = promotes + list(set(['nodes', 'element_mass', 'load_factor']))
        if surface['distributed_fuel_weight']:
            promotes = promotes + list(set(['nodes', 'load_factor']))

        self.add_subsystem('struct_states',
            SpatialBeamStates(surface=surface),
            promotes_inputs=['local_stiff_transformed', 'forces', 'loads'] + promotes,
            promotes_outputs=['disp'])
        if surface['fem_model_type'] == 'tube':
            self.add_subsystem('struct_funcs',
                SpatialBeamFunctionals(surface=surface),
                promotes_inputs=['thickness', 'radius', 'nodes', 'disp'],
                promotes_outputs=['thickness_intersects', 'vonmises', 'failure'])
        else:
            self.add_subsystem('struct_funcs',
                SpatialBeamFunctionals(surface=surface),
                promotes_inputs=['spar_thickness', 'disp','Qz', 'J', 'A_enc', 'htop', 'hbottom', 'hfront', 'hrear', 'nodes'],
                promotes_outputs=['vonmises', 'failure'])
Exemplo n.º 20
0
    def test(self):

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 5,
            'num_x': 2,
            'wing_type': 'rect',
            'symmetry': False
        }

        mesh = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name': 'wing',  # name of the surface
            'type': 'aero',
            'symmetry': False,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type': 'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'twist_cp': np.array([0.]),
            'mesh': mesh,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0': 0.0,  # CL of the surface at alpha=0
            'CD0': 0.015,  # CD of the surface at 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_cp':
            np.array([0.15]),  # thickness over chord ratio (NACA0015)
            'c_max_t': .303,  # chordwise location of maximum (NACA0015)
            # thickness
            'with_viscous': True,
            'with_wave': False,  # if true, compute wave drag
        }

        surfaces = [surf_dict]

        # Create the problem and the model group
        prob = om.Problem()

        indep_var_comp = om.IndepVarComp()
        indep_var_comp.add_output('v', val=248.136, units='m/s')
        indep_var_comp.add_output('alpha', val=5., units='deg')
        indep_var_comp.add_output('omega',
                                  val=np.array([30.0, 0.0, 0.0]),
                                  units='deg/s')
        indep_var_comp.add_output('Mach_number', val=0.84)
        indep_var_comp.add_output('re', val=1.e6, units='1/m')
        indep_var_comp.add_output('rho', val=0.38, units='kg/m**3')
        indep_var_comp.add_output('cg', val=np.zeros((3)), units='m')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

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

            geom_group = Geometry(surface=surface)

            # Add tmp_group to the problem as the name of the surface.
            # Note that is a group and performance group for each
            # individual surface.
            prob.model.add_subsystem(surface['name'], geom_group)

        # Loop through and add a certain number of aero points
        for i in range(1):

            # Create the aero point group and add it to the model
            aero_group = AeroPoint(surfaces=surfaces, rotational=True)
            point_name = 'aero_point_{}'.format(i)
            prob.model.add_subsystem(point_name, aero_group)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('omega', point_name + '.omega')
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('cg', point_name + '.cg')

            # Connect the parameters within the model for each aero point
            for surface in surfaces:

                name = surface['name']

                # Connect the mesh from the geometry component to the analysis point
                prob.model.connect(name + '.mesh',
                                   point_name + '.' + name + '.def_mesh')

                # Perform the connections with the modified names within the
                # 'aero_states' group.
                prob.model.connect(
                    name + '.mesh',
                    point_name + '.aero_states.' + name + '_def_mesh')

                prob.model.connect(
                    name + '.t_over_c',
                    point_name + '.' + name + '_perf.' + 't_over_c')

        # Set up the problem
        prob.setup()

        prob.run_model()

        assert_rel_error(self, prob['aero_point_0.wing_perf.CD'][0],
                         0.034758588209493596, 1e-6)
        assert_rel_error(self, prob['aero_point_0.wing_perf.CL'][0],
                         0.46156798274410005, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][0], 0.07287199378862094,
                         1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][1],
                         -0.11507066985988826, 1e-6)
        assert_rel_error(self, prob['aero_point_0.CM'][2],
                         0.010803003923282652, 1e-6)