def test_aerostruct_optimization_symmetry_multiple(self): OAS_prob = OASProblem({'type' : 'aerostruct', 'optimize' : True}) surf_dict = {'name' : 'wing', 'symmetry' : True, 'num_y' : 13, 'num_x' : 2, 'wing_type' : 'CRM', 'CL0' : 0.2, 'CD0' : 0.015} OAS_prob.add_surface(surf_dict) surf_dict.update({'name' : 'tail', 'offset':numpy.array([0., 0., 1.e7])}) OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.add_desvar('wing_twist_cp', lower=-15., upper=15.) OAS_prob.add_desvar('wing_thickness_cp', lower=0.01, upper=0.25, scaler=1e2) OAS_prob.add_constraint('wing_failure', upper=0.) OAS_prob.add_desvar('tail_twist_cp', lower=-15., upper=15.) OAS_prob.add_desvar('tail_thickness_cp', lower=0.01, upper=0.25, scaler=1e2) OAS_prob.add_constraint('tail_failure', upper=0.) OAS_prob.add_desvar('alpha', lower=-10., upper=10.) OAS_prob.add_constraint('eq_con', equals=0.) OAS_prob.add_objective('fuelburn', scaler=1e-5) OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['fuelburn'], 1708184.640125683, places=0) self.assertAlmostEqual(prob['wing_failure'], 1e-9) self.assertAlmostEqual(numpy.linalg.norm(prob['wing_twist_cp']), numpy.linalg.norm(prob['tail_twist_cp']), places=3)
def test_aero_multiple_opt(self): OAS_prob = OASProblem({'type': 'aero', 'optimize': True}) surf_dict = { 'name': 'wing', 'span': 5., 'num_y': 3, 'span_cos_spacing': 0. } OAS_prob.add_surface(surf_dict) surf_dict.update({ 'name': 'tail', 'offset': numpy.array([0., 0., 10.]) }) OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.add_desvar('tail.twist_cp', lower=-10., upper=15.) OAS_prob.add_desvar('tail.sweep', lower=10., upper=30.) OAS_prob.add_desvar('tail.dihedral', lower=-10., upper=20.) OAS_prob.add_desvar('tail.taper', lower=.5, upper=2.) OAS_prob.add_constraint('tail_perf.CL', equals=0.5) OAS_prob.add_objective('tail_perf.CD', scaler=1e4) OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['wing_perf.CL'], .41543435621928004, places=5) self.assertAlmostEqual(prob['tail_perf.CL'], .5, places=5) self.assertAlmostEqual(prob['wing_perf.CD'], .0075400306289957033, places=5) self.assertAlmostEqual(prob['tail_perf.CD'], .00791118243006308, places=5)
def test_aerostruct_optimization_symmetry(self): OAS_prob = OASProblem({'type': 'aerostruct', 'optimize': True}) surf_dict = { 'symmetry': True, 'num_y': 13, 'num_x': 2, 'wing_type': 'CRM', 'CL0': 0.2, 'CD0': 0.015 } OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.add_desvar('wing.twist_cp', lower=-15., upper=15.) OAS_prob.add_desvar('wing.thickness_cp', lower=0.01, upper=0.25, scaler=1e2) OAS_prob.add_constraint('wing_perf.failure', upper=0.) OAS_prob.add_desvar('alpha', lower=-10., upper=10.) OAS_prob.add_constraint('eq_con', equals=0.) OAS_prob.add_objective('fuelburn', scaler=1e-4) OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['fuelburn'], 80248.113842385414, places=0) self.assertAlmostEqual(prob['wing_perf.failure'], 1e-9)
def test_aero_analysis_flat_symmetry(self): OAS_prob = OASProblem({'type': 'aero', 'optimize': False}) surf_dict = {'symmetry': True} OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['wing_perf.CL'], .45655138, places=5)
def test_struct_analysis_symmetry(self): OAS_prob = OASProblem({'type': 'struct', 'optimize': False}) surf_dict = {'symmetry': True} OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['wing.weight'], 83.2113646, places=3)
def test_aero_analysis_flat(self): OAS_prob = OASProblem({'type': 'aero', 'optimize': False}) OAS_prob.add_surface({'span_cos_spacing': 0}) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['wing_perf.CL'], .46173591841167, places=5) self.assertAlmostEqual(prob['wing_perf.CD'], .005524603647, places=5)
def test_aero_analysis_flat_multiple(self): OAS_prob = OASProblem({'type' : 'aero', 'optimize' : False}) OAS_prob.add_surface({'span_cos_spacing' : 0.}) OAS_prob.add_surface({'name' : 'tail', 'span_cos_spacing' : 0., 'offset' : numpy.array([0., 0., 1000000.])}) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['CL'], .46173591841167, places=5) self.assertAlmostEqual(prob['tail_CL'], .46173591841167, places=5)
def test_struct_optimization(self): OAS_prob = OASProblem({'type' : 'struct', 'optimize' : True}) OAS_prob.add_surface() OAS_prob.setup() OAS_prob.add_desvar('thickness_cp', lower=0.01, upper=0.25, scaler=1e2) OAS_prob.add_constraint('failure', upper=0.) OAS_prob.add_objective('weight', scaler=1e-3) OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['weight'], 2010.4792274, places=2)
def test_struct_optimization_symmetry(self): OAS_prob = OASProblem({'type' : 'struct', 'optimize' : True}) surf_dict = {'symmetry' : True} OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.add_desvar('thickness_cp', lower=0.01, upper=0.25, scaler=1e2) OAS_prob.add_constraint('failure', upper=0.) OAS_prob.add_objective('weight', scaler=1e-3) OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['weight'], 1908.6362044761127, places=2)
def test_aerostruct_analysis(self): OAS_prob = OASProblem({'type' : 'aerostruct', 'optimize' : False}) surf_dict = {'num_y' : 13, 'num_x' : 2, 'wing_type' : 'CRM', 'CL0' : 0.2, 'CD0' : 0.015} OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['CL'], .58245256) self.assertAlmostEqual(prob['failure'], -.431801158, places=5) self.assertAlmostEqual(prob['fuelburn'], 1400891.8033734, places=2)
def test_aero_optimization_flat(self): OAS_prob = OASProblem({'type' : 'aero', 'optimize' : True}) OAS_prob.add_surface() OAS_prob.setup() OAS_prob.add_desvar('twist_cp', lower=-10., upper=15.) OAS_prob.add_desvar('sweep', lower=10., upper=30.) OAS_prob.add_desvar('dihedral', lower=-10., upper=20.) OAS_prob.add_desvar('taper', lower=.5, upper=2.) OAS_prob.add_constraint('CL', equals=0.5) OAS_prob.add_objective('CD', scaler=1e4) OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['CD'], .004048702908627036, places=5)
def test_aerostruct_analysis_symmetry(self): OAS_prob = OASProblem({'type': 'aerostruct', 'optimize': False}) surf_dict = { 'symmetry': True, 'num_y': 13, 'num_x': 2, 'wing_type': 'CRM', 'CL0': 0.2, 'CD0': 0.015 } OAS_prob.add_surface(surf_dict) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['wing_perf.CL'], .58245256) self.assertAlmostEqual(prob['wing_perf.failure'], -.5011158763, places=5) self.assertAlmostEqual(prob['fuelburn'], 139970.19140120025, places=2)
def test_aero_analysis_flat_side_by_side(self): OAS_prob = OASProblem({'type' : 'aero', 'optimize' : False}) OAS_prob.add_surface({'name' : 'wing', 'span' : 5., 'num_y' : 3, 'span_cos_spacing' : 0., 'offset' : numpy.array([0., -2.5, 0.])}) OAS_prob.add_surface({'name' : 'tail', 'span' : 5., 'num_y' : 3, 'span_cos_spacing' : 0., 'offset' : numpy.array([0., 2.5, 0.])}) OAS_prob.setup() OAS_prob.run() prob = OAS_prob.prob self.assertAlmostEqual(prob['wing_CL'], .46173591841167, places=5) self.assertAlmostEqual(prob['tail_CL'], .46173591841167, places=5) self.assertAlmostEqual(prob['wing_CD'], .005524603647, places=5) self.assertAlmostEqual(prob['tail_CD'], .005524603647, places=5)
) print( ' +---------------------------------------------------------------+\n' ) raise # Set problem type prob_dict = {'type': 'aero'} if sys.argv[1].startswith('0'): # run analysis once prob_dict.update({'optimize': False}) else: # perform optimization prob_dict.update({'optimize': True}) # Instantiate problem and add default surface OAS_prob = OASProblem(prob_dict) OAS_prob.add_surface({ 'name': 'wing', 'symmetry': True, 'num_y': 5, 'num_x': 3 }) # Single lifting surface if not sys.argv[1].endswith('m'): # Setup problem and add design variables, constraint, and objective OAS_prob.setup() OAS_prob.add_desvar('wing.twist_cp', lower=-10., upper=15.) OAS_prob.add_desvar('wing.sweep', lower=10., upper=30.) OAS_prob.add_desvar('wing.dihedral', lower=-10., upper=20.)
def setup(prob_dict={}, surfaces=[{}]): ''' Setup the aerostruct mesh Default wing mesh (single lifting surface): ------------------------------------------- name = 'wing' # name of the surface num_x = 3 # number of chordwise points num_y = 5 # number of spanwise points root_chord = 1. # root chord span_cos_spacing = 1 # 0 for uniform spanwise panels # 1 for cosine-spaced panels # any value between 0 and 1 for a mixed spacing chord_cos_spacing = 0. # 0 for uniform chordwise panels # 1 for cosine-spaced panels # any value between 0 and 1 for a mixed spacing wing_type = 'rect' # initial shape of the wing either 'CRM' or 'rect' # 'CRM' can have different options after it, such as 'CRM:alpha_2.75' for the CRM shape at alpha=2.75 offset = np.array([0., 0., 0.]) # coordinates to offset the surface from its default location symmetry = True # if true, model one half of wing reflected across the plane y = 0 S_ref_type = 'wetted' # 'wetted' or 'projected' # Simple Geometric Variables span = 10. # full wingspan dihedral = 0. # wing dihedral angle in degrees positive is upward sweep = 0. # wing sweep angle in degrees positive sweeps back taper = 1. # taper ratio; 1. is uniform chord # B-spline Geometric Variables. The number of control points for each of these variables can be specified in surf_dict # by adding the prefix "num" to the variable (e.g. num_twist) twist_cp = None chord_cp = None xshear_cp = None zshear_cp = None thickness_cp = None Default wing parameters: ------------------------ Zero-lift aerodynamic performance CL0 = 0.0 # CL value at AoA (alpha) = 0 CD0 = 0.0 # CD value at AoA (alpha) = 0 Airfoil properties for viscous drag calculation k_lam = 0.05 # percentage of chord with laminar flow, used for viscous drag t_over_c = 0.12 # thickness over chord ratio (NACA0012) c_max_t = .303 # chordwise location of maximum (NACA0012) thickness Structural values are based on aluminum E = 70.e9 # [Pa] Young's modulus of the spar G = 30.e9 # [Pa] shear modulus of the spar stress = 20.e6 # [Pa] yield stress mrho = 3.e3 # [kg/m^3] material density fem_origin = 0.35 # chordwise location of the spar Other W0 = 0.4 * 3e5 # [kg] MTOW of B777 is 3e5 kg with fuel Default problem parameters: --------------------------- Re = 1e6 # Reynolds number reynolds_length = 1.0 # characteristic Reynolds length alpha = 5. # angle of attack CT = 9.80665 * 17.e-6 # [1/s] (9.81 N/kg * 17e-6 kg/N/s) R = 14.3e6 # [m] maximum range M = 0.84 # Mach number at cruise rho = 0.38 # [kg/m^3] air density at 35,000 ft a = 295.4 # [m/s] speed of sound at 35,000 ft with_viscous = False # if true, compute viscous drag ''' # Use steps in run_aerostruct.py to add wing surface to problem # Set problem type prob_dict.update({ 'type': 'aerostruct' }) # this doesn't really matter since we aren't calling OASProblem.setup() # Instantiate problem OAS_prob = OASProblem(prob_dict) for surface in surfaces: # Add SpatialBeamFEM size FEMsize = 6 * surface['num_y'] + 6 surface.update({'FEMsize': FEMsize}) # Add the specified wing surface to the problem. OAS_prob.add_surface(surface) # Add materials properties for the wing surface to the surface dict in OAS_prob for idx, surface in enumerate(OAS_prob.surfaces): A, Iy, Iz, J = materials_tube(surface['radius'], surface['thickness'], surface) OAS_prob.surfaces[idx].update({'A': A, 'Iy': Iy, 'Iz': Iz, 'J': J}) # Get total panels and save in prob_dict tot_panels = 0 for surface in OAS_prob.surfaces: ny = surface['num_y'] nx = surface['num_x'] tot_panels += (nx - 1) * (ny - 1) OAS_prob.prob_dict.update({'tot_panels': tot_panels}) # Assume we are only using a single lifting surface for now surface = OAS_prob.surfaces[0] # Initialize the OpenAeroStruct components and save them in a component dictionary comp_dict = {} comp_dict['MaterialsTube'] = MaterialsTube(surface) comp_dict['GeometryMesh'] = GeometryMesh(surface) comp_dict['TransferDisplacements'] = TransferDisplacements(surface) comp_dict['VLMGeometry'] = VLMGeometry(surface) comp_dict['AssembleAIC'] = AssembleAIC([surface]) comp_dict['AeroCirculations'] = AeroCirculations( OAS_prob.prob_dict['tot_panels']) comp_dict['VLMForces'] = VLMForces([surface]) comp_dict['TransferLoads'] = TransferLoads(surface) comp_dict['ComputeNodes'] = ComputeNodes(surface) comp_dict['AssembleK'] = AssembleK(surface) comp_dict['SpatialBeamFEM'] = SpatialBeamFEM(surface['FEMsize']) comp_dict['SpatialBeamDisp'] = SpatialBeamDisp(surface) OAS_prob.comp_dict = comp_dict return OAS_prob
def setup(prob_dict={}, surfaces=[{}]): ''' Setup the aerostruct mesh Default wing mesh (single lifting surface): ------------------------------------------- name = 'wing' # name of the surface num_x = 3 # number of chordwise points num_y = 5 # number of spanwise points root_chord = 1. # root chord span_cos_spacing = 1 # 0 for uniform spanwise panels # 1 for cosine-spaced panels # any value between 0 and 1 for a mixed spacing chord_cos_spacing = 0. # 0 for uniform chordwise panels # 1 for cosine-spaced panels # any value between 0 and 1 for a mixed spacing wing_type = 'rect' # initial shape of the wing either 'CRM' or 'rect' # 'CRM' can have different options after it, such as 'CRM:alpha_2.75' for the CRM shape at alpha=2.75 offset = np.array([0., 0., 0.]) # coordinates to offset the surface from its default location symmetry = True # if true, model one half of wing reflected across the plane y = 0 S_ref_type = 'wetted' # 'wetted' or 'projected' # Simple Geometric Variables span = 10. # full wingspan dihedral = 0. # wing dihedral angle in degrees positive is upward sweep = 0. # wing sweep angle in degrees positive sweeps back taper = 1. # taper ratio; 1. is uniform chord # B-spline Geometric Variables. The number of control points for each of these variables can be specified in surf_dict # by adding the prefix "num" to the variable (e.g. num_twist) twist_cp = None chord_cp = None xshear_cp = None zshear_cp = None thickness_cp = None Default wing parameters: ------------------------ Zero-lift aerodynamic performance CL0 = 0.0 # CL value at AoA (alpha) = 0 CD0 = 0.0 # CD value at AoA (alpha) = 0 Airfoil properties for viscous drag calculation k_lam = 0.05 # percentage of chord with laminar flow, used for viscous drag t_over_c = 0.12 # thickness over chord ratio (NACA0012) c_max_t = .303 # chordwise location of maximum (NACA0012) thickness Structural values are based on aluminum E = 70.e9 # [Pa] Young's modulus of the spar G = 30.e9 # [Pa] shear modulus of the spar <<<<<<< HEAD stress = 20.e6 # [Pa] yield stress ======= yield = 20.e6 # [Pa] yield stress >>>>>>> 7eefd15e6c26c95cbbd9f303d23ecb4716c2fea3 mrho = 3.e3 # [kg/m^3] material density fem_origin = 0.35 # chordwise location of the spar Other W0 = 0.4 * 3e5 # [kg] MTOW of B777 is 3e5 kg with fuel Default problem parameters: --------------------------- Re = 1e6 # Reynolds number reynolds_length = 1.0 # characteristic Reynolds length alpha = 5. # angle of attack CT = 9.80665 * 17.e-6 # [1/s] (9.81 N/kg * 17e-6 kg/N/s) R = 14.3e6 # [m] maximum range M = 0.84 # Mach number at cruise rho = 0.38 # [kg/m^3] air density at 35,000 ft a = 295.4 # [m/s] speed of sound at 35,000 ft with_viscous = False # if true, compute viscous drag ''' # Use steps in run_aerostruct.py to add wing surface to problem # Set problem type prob_dict.update({'type' : 'aerostruct'}) # this doesn't really matter since we aren't calling OASProblem.setup() # Instantiate problem OAS_prob = OASProblem(prob_dict) for surface in surfaces: # Add SpatialBeamFEM size FEMsize = 6 * surface['num_y'] + 6 surface.update({'FEMsize': FEMsize}) # Add the specified wing surface to the problem. OAS_prob.add_surface(surface) # Add materials properties for the wing surface to the surface dict in OAS_prob for idx, surface in enumerate(OAS_prob.surfaces):