def vlm_geometry(def_mesh, comp): """ Compute various geometric properties for VLM analysis. Parameters ---------- def_mesh[nx, ny, 3] : numpy array Array defining the nodal coordinates of the lifting surface. comp : Either OpenAeroStruct component object (better), or surface dict. Returns ------- b_pts[nx-1, ny, 3] : numpy array Bound points for the horseshoe vortices, found along the 1/4 chord. c_pts[nx-1, ny-1, 3] : numpy array Collocation points on the 3/4 chord line where the flow tangency condition is satisfed. Used to set up the linear system. widths[nx-1, ny-1] : numpy array The spanwise widths of each individual panel. lengths[ny] : numpy array The chordwise length of the entire airfoil following the camber line. normals[nx-1, ny-1, 3] : numpy array The normal vector for each panel, computed as the cross of the two diagonals from the mesh points. S_ref : float The reference area of the lifting surface. """ if not isinstance(comp, Component): surface = comp comp = VLMGeometry(surface) params = { 'def_mesh': def_mesh } unknowns = { 'b_pts': np.zeros((comp.nx-1, comp.ny, 3), dtype=data_type), 'c_pts': np.zeros((comp.nx-1, comp.ny-1, 3)), 'widths': np.zeros((comp.ny-1)), 'cos_sweep': np.zeros((comp.ny-1)), 'lengths': np.zeros((comp.ny)), 'normals': np.zeros((comp.nx-1, comp.ny-1, 3)), 'S_ref': 0. } resids=None comp.solve_nonlinear(params, unknowns, resids) b_pts=unknowns.get('b_pts') c_pts=unknowns.get('c_pts') widths=unknowns.get('widths') cos_sweep=unknowns.get('cos_sweep') lengths=unknowns.get('lengths') normals=unknowns.get('normals') S_ref=unknowns.get('S_ref') return b_pts, c_pts, widths, cos_sweep, lengths, normals, S_ref
def vlm_geometry(def_mesh, comp): """ Compute various geometric properties for VLM analysis. Parameters ---------- def_mesh[nx, ny, 3] : numpy array Array defining the nodal coordinates of the lifting surface. comp : Either OpenAeroStruct component object (better), or surface dict. Returns ------- b_pts[nx-1, ny, 3] : numpy array Bound points for the horseshoe vortices, found along the 1/4 chord. c_pts[nx-1, ny-1, 3] : numpy array Collocation points on the 3/4 chord line where the flow tangency condition is satisfed. Used to set up the linear system. widths[nx-1, ny-1] : numpy array The spanwise widths of each individual panel. lengths[ny] : numpy array The chordwise length of the entire airfoil following the camber line. normals[nx-1, ny-1, 3] : numpy array The normal vector for each panel, computed as the cross of the two diagonals from the mesh points. S_ref : float The reference area of the lifting surface. """ if not isinstance(comp, Component): surface = comp comp = VLMGeometry(surface) params = {'def_mesh': def_mesh} unknowns = { 'b_pts': np.zeros((comp.nx - 1, comp.ny, 3), dtype=data_type), 'c_pts': np.zeros((comp.nx - 1, comp.ny - 1, 3)), 'widths': np.zeros((comp.ny - 1)), 'cos_sweep': np.zeros((comp.ny - 1)), 'lengths': np.zeros((comp.ny)), 'normals': np.zeros((comp.nx - 1, comp.ny - 1, 3)), 'S_ref': 0. } resids = None comp.solve_nonlinear(params, unknowns, resids) b_pts = unknowns.get('b_pts') c_pts = unknowns.get('c_pts') widths = unknowns.get('widths') cos_sweep = unknowns.get('cos_sweep') lengths = unknowns.get('lengths') normals = unknowns.get('normals') S_ref = unknowns.get('S_ref') return b_pts, c_pts, widths, cos_sweep, lengths, normals, S_ref
('rho', prob_dict['rho']), ('r', r), ('M', prob_dict['M']), ('Re', prob_dict['Re']), ] ############################################################### # Problem 2a: # These are your components. Here we simply create the objects. ############################################################### indep_vars_comp = IndepVarComp(indep_vars) tube_comp = MaterialsTube(surface) mesh_comp = GeometryMesh(surface) geom_comp = VLMGeometry(surface) spatialbeamstates_comp = SpatialBeamStates(surface) def_mesh_comp = TransferDisplacements(surface) vlmstates_comp = VLMStates(OAS_prob.surfaces, OAS_prob.prob_dict) loads_comp = TransferLoads(surface) vlmfuncs_comp = VLMFunctionals(surface) spatialbeamfuncs_comp = SpatialBeamFunctionals(surface) fuelburn_comp = FunctionalBreguetRange(OAS_prob.surfaces, OAS_prob.prob_dict) eq_con_comp = FunctionalEquilibrium(OAS_prob.surfaces, OAS_prob.prob_dict) ################################################################# # Problem 2a: # Now add the components you created above to the correct groups. # indep_vars_comp, tube_comp, and vlm_funcs have been
def setup_aerostruct(self): """ Specific method to add the necessary components to the problem for an aerostructural problem. """ # Set the problem name if the user doesn't if 'prob_name' not in self.prob_dict.keys(): self.prob_dict['prob_name'] = 'aerostruct' # Create the base root-level group root = Group() coupled = Group() # Create the problem and assign the root group self.prob = Problem() self.prob.root = root # Loop over each surface in the surfaces list for surface in self.surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] tmp_group = Group() # Add independent variables that do not belong to a specific component indep_vars = [ ('twist_cp', numpy.zeros(surface['num_twist'])), ('thickness_cp', numpy.ones(surface['num_thickness']) * numpy.max(surface['t'])), ('r', surface['r']), ('dihedral', surface['dihedral']), ('sweep', surface['sweep']), ('span', surface['span']), ('taper', surface['taper']) ] # Obtain the Jacobians to interpolate the data from the b-spline # control points jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y']) jac_thickness = get_bspline_mtx(surface['num_thickness'], surface['num_y'] - 1) # Add components to include in the surface's group tmp_group.add('indep_vars', IndepVarComp(indep_vars), promotes=['*']) tmp_group.add('twist_bsp', Bspline('twist_cp', 'twist', jac_twist), promotes=['*']) tmp_group.add('thickness_bsp', Bspline('thickness_cp', 'thickness', jac_thickness), promotes=['*']) tmp_group.add('tube', MaterialsTube(surface), promotes=['*']) # Add tmp_group to the problem with the name of the surface. name_orig = name name = name[:-1] exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=[])') # Add components to the 'coupled' group for each surface. # The 'coupled' group must contain all components and parameters # needed to converge the aerostructural system. tmp_group = Group() tmp_group.add('mesh', GeometryMesh(surface), promotes=['*']) tmp_group.add('def_mesh', TransferDisplacements(surface), promotes=['*']) tmp_group.add('aero_geom', VLMGeometry(surface), promotes=['*']) tmp_group.add('struct_states', SpatialBeamStates(surface), promotes=['*']) tmp_group.struct_states.ln_solver = LinearGaussSeidel() name = name_orig exec(name + ' = tmp_group') exec('coupled.add("' + name[:-1] + '", ' + name + ', promotes=[])') # Add a loads component to the coupled group exec('coupled.add("' + name_orig + 'loads' + '", ' + 'TransferLoads(surface)' + ', promotes=[])') # Add a performance group which evaluates the data after solving # the coupled system tmp_group = Group() tmp_group.add('struct_funcs', SpatialBeamFunctionals(surface), promotes=['*']) tmp_group.add('aero_funcs', VLMFunctionals(surface), promotes=['*']) name = name_orig + 'perf' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["rho", "v", "alpha", "Re", "M"])') # Add a single 'aero_states' component for the whole system within the # coupled group. coupled.add('aero_states', VLMStates(self.surfaces, self.prob_dict), promotes=['v', 'alpha', 'rho']) # Explicitly connect parameters from each surface's group and the common # 'aero_states' group. for surface in self.surfaces: name = surface['name'] # Perform the connections with the modified names within the # 'aero_states' group. root.connect('coupled.' + name[:-1] + '.def_mesh', 'coupled.aero_states.' + name + 'def_mesh') root.connect('coupled.' + name[:-1] + '.b_pts', 'coupled.aero_states.' + name + 'b_pts') root.connect('coupled.' + name[:-1] + '.c_pts', 'coupled.aero_states.' + name + 'c_pts') root.connect('coupled.' + name[:-1] + '.normals', 'coupled.aero_states.' + name + 'normals') # Connect the results from 'aero_states' to the performance groups root.connect('coupled.aero_states.' + name + 'sec_forces', name + 'perf' + '.sec_forces') # Connect the results from 'coupled' to the performance groups root.connect('coupled.' + name[:-1] + '.def_mesh', 'coupled.' + name + 'loads.def_mesh') root.connect('coupled.aero_states.' + name + 'sec_forces', 'coupled.' + name + 'loads.sec_forces') root.connect('coupled.' + name + 'loads.loads', name + 'perf.loads') # Connect the output of the loads component with the FEM # displacement parameter. This links the coupling within the coupled # group that necessitates the subgroup solver. root.connect('coupled.' + name + 'loads.loads', 'coupled.' + name[:-1] + '.loads') # Connect aerodyamic design variables root.connect(name[:-1] + '.dihedral', 'coupled.' + name[:-1] + '.dihedral') root.connect(name[:-1] + '.span', 'coupled.' + name[:-1] + '.span') root.connect(name[:-1] + '.sweep', 'coupled.' + name[:-1] + '.sweep') root.connect(name[:-1] + '.taper', 'coupled.' + name[:-1] + '.taper') root.connect(name[:-1] + '.twist', 'coupled.' + name[:-1] + '.twist') # Connect structural design variables root.connect(name[:-1] + '.A', 'coupled.' + name[:-1] + '.A') root.connect(name[:-1] + '.Iy', 'coupled.' + name[:-1] + '.Iy') root.connect(name[:-1] + '.Iz', 'coupled.' + name[:-1] + '.Iz') root.connect(name[:-1] + '.J', 'coupled.' + name[:-1] + '.J') # Connect performance calculation variables root.connect(name[:-1] + '.r', name + 'perf.r') root.connect(name[:-1] + '.A', name + 'perf.A') # Connection performance functional variables root.connect(name + 'perf.weight', 'fuelburn.' + name + 'weight') root.connect(name + 'perf.weight', 'eq_con.' + name + 'weight') root.connect(name + 'perf.L', 'eq_con.' + name + 'L') root.connect(name + 'perf.CL', 'fuelburn.' + name + 'CL') root.connect(name + 'perf.CD', 'fuelburn.' + name + 'CD') # Connect paramters from the 'coupled' group to the performance # group. root.connect('coupled.' + name[:-1] + '.nodes', name + 'perf.nodes') root.connect('coupled.' + name[:-1] + '.disp', name + 'perf.disp') root.connect('coupled.' + name[:-1] + '.S_ref', name + 'perf.S_ref') # Set solver properties for the coupled group coupled.ln_solver = ScipyGMRES() coupled.ln_solver.options['iprint'] = 1 coupled.ln_solver.preconditioner = LinearGaussSeidel() coupled.aero_states.ln_solver = LinearGaussSeidel() coupled.nl_solver = NLGaussSeidel() coupled.nl_solver.options['iprint'] = 1 # Ensure that the groups are ordered correctly within the coupled group # so that a system with multiple surfaces is solved corretly. order_list = [] for surface in self.surfaces: order_list.append(surface['name'][:-1]) order_list.append('aero_states') for surface in self.surfaces: order_list.append(surface['name'] + 'loads') coupled.set_order(order_list) # Add the coupled group to the root problem root.add('coupled', coupled, promotes=['v', 'alpha', 'rho']) # Add problem information as an independent variables component prob_vars = [('v', self.prob_dict['v']), ('alpha', self.prob_dict['alpha']), ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']), ('rho', self.prob_dict['rho'])] root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*']) # Add functionals to evaluate performance of the system. # Note that only the interesting results are promoted here; not all # of the parameters. root.add('fuelburn', FunctionalBreguetRange(self.surfaces, self.prob_dict), promotes=['fuelburn']) root.add('eq_con', FunctionalEquilibrium(self.surfaces, self.prob_dict), promotes=['eq_con', 'fuelburn']) # Actually set up the system self.setup_prob()
def setup_aero(self): """ Specific method to add the necessary components to the problem for an aerodynamic problem. """ # Set the problem name if the user doesn't if 'prob_name' not in self.prob_dict.keys(): self.prob_dict['prob_name'] = 'aero' # Create the base root-level group root = Group() # Create the problem and assign the root group self.prob = Problem() self.prob.root = root # Loop over each surface in the surfaces list for surface in self.surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] tmp_group = Group() # Add independent variables that do not belong to a specific component indep_vars = [('twist_cp', numpy.zeros(surface['num_twist'])), ('dihedral', surface['dihedral']), ('sweep', surface['sweep']), ('span', surface['span']), ('taper', surface['taper']), ('disp', numpy.zeros((surface['num_y'], 6)))] # Obtain the Jacobian to interpolate the data from the b-spline # control points jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y']) # Add aero components to the surface-specific group tmp_group.add('indep_vars', IndepVarComp(indep_vars), promotes=['*']) tmp_group.add('twist_bsp', Bspline('twist_cp', 'twist', jac_twist), promotes=['*']) tmp_group.add('mesh', GeometryMesh(surface), promotes=['*']) tmp_group.add('def_mesh', TransferDisplacements(surface), promotes=['*']) tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*']) # Add tmp_group to the problem as the name of the surface. # Note that is a group and performance group for each # individual surface. name_orig = name.strip('_') name = name_orig exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=[])') # Add a performance group for each surface name = name_orig + '_perf' exec('root.add("' + name + '", ' + 'VLMFunctionals(surface)' + ', promotes=["v", "alpha", "M", "Re", "rho"])') # Add problem information as an independent variables component prob_vars = [('v', self.prob_dict['v']), ('alpha', self.prob_dict['alpha']), ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']), ('rho', self.prob_dict['rho'])] root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*']) # Add a single 'aero_states' component that solves for the circulations # and forces from all the surfaces. # While other components only depends on a single surface, # this component requires information from all surfaces because # each surface interacts with the others. root.add('aero_states', VLMStates(self.surfaces, self.prob_dict), promotes=['circulations', 'v', 'alpha', 'rho']) # Explicitly connect parameters from each surface's group and the common # 'aero_states' group. # This is necessary because the VLMStates component requires information # from each surface, but this information is stored within each # surface's group. for surface in self.surfaces: name = surface['name'] # Perform the connections with the modified names within the # 'aero_states' group. root.connect(name[:-1] + '.def_mesh', 'aero_states.' + name + 'def_mesh') root.connect(name[:-1] + '.b_pts', 'aero_states.' + name + 'b_pts') root.connect(name[:-1] + '.c_pts', 'aero_states.' + name + 'c_pts') root.connect(name[:-1] + '.normals', 'aero_states.' + name + 'normals') # Connect the results from 'aero_states' to the performance groups root.connect('aero_states.' + name + 'sec_forces', name + 'perf' + '.sec_forces') # Connect S_ref for performance calcs root.connect(name[:-1] + '.S_ref', name + 'perf' + '.S_ref') # Actually set up the problem self.setup_prob()
def setup_aerostruct(self): """ Specific method to add the necessary components to the problem for an aerostructural problem. """ # Set the problem name if the user doesn't if 'prob_name' not in self.prob_dict.keys(): self.prob_dict['prob_name'] = 'aerostruct' # Create the base root-level group root = Group() coupled = Group() # Create the problem and assign the root group self.prob = Problem() self.prob.root = root # Loop over each surface in the surfaces list for surface in self.surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] tmp_group = Group() # Add independent variables that do not belong to a specific component indep_vars = [ (name + 'twist_cp', numpy.zeros(surface['num_twist'])), (name + 'thickness_cp', numpy.ones(surface['num_thickness']) * numpy.max(surface['t'])), (name + 'r', surface['r']), (name + 'dihedral', surface['dihedral']), (name + 'sweep', surface['sweep']), (name + 'span', surface['span']), (name + 'taper', surface['taper']) ] # Obtain the Jacobians to interpolate the data from the b-spline # control points jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y']) jac_thickness = get_bspline_mtx(surface['num_thickness'], surface['num_y'] - 1) # Add components to include in the '_pre_solve' group tmp_group.add('indep_vars', IndepVarComp(indep_vars), promotes=['*']) tmp_group.add('twist_bsp', Bspline(name + 'twist_cp', name + 'twist', jac_twist), promotes=['*']) tmp_group.add('thickness_bsp', Bspline(name + 'thickness_cp', name + 'thickness', jac_thickness), promotes=['*']) tmp_group.add('tube', MaterialsTube(surface), promotes=['*']) # Add tmp_group to the problem with the name of the surface and # '_pre_solve' appended. name_orig = name #.strip('_') name = name + 'pre_solve' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["*"])') # Add components to the 'coupled' group for each surface tmp_group = Group() tmp_group.add('mesh', GeometryMesh(surface), promotes=['*']) tmp_group.add('def_mesh', TransferDisplacements(surface), promotes=['*']) tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*']) tmp_group.add('spatialbeamstates', SpatialBeamStates(surface), promotes=['*']) tmp_group.spatialbeamstates.ln_solver = LinearGaussSeidel() name = name_orig + 'group' exec(name + ' = tmp_group') exec('coupled.add("' + name + '", ' + name + ', promotes=["*"])') # Add a loads component to the coupled group exec('coupled.add("' + name_orig + 'loads' + '", ' + 'TransferLoads(surface)' + ', promotes=["*"])') # Add a '_post_solve' group which evaluates the data after solving # the coupled system tmp_group = Group() tmp_group.add('spatialbeamfuncs', SpatialBeamFunctionals(surface), promotes=['*']) tmp_group.add('vlmfuncs', VLMFunctionals(surface), promotes=['*']) name = name_orig + 'post_solve' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["*"])') # Add a single 'VLMStates' component for the whole system coupled.add('vlmstates', VLMStates(self.surfaces, self.prob_dict), promotes=['*']) # Set solver properties for the coupled group coupled.ln_solver = ScipyGMRES() coupled.ln_solver.options['iprint'] = 1 coupled.ln_solver.preconditioner = LinearGaussSeidel() coupled.vlmstates.ln_solver = LinearGaussSeidel() coupled.nl_solver = NLGaussSeidel() coupled.nl_solver.options['iprint'] = 1 # Ensure that the groups are ordered correctly within the coupled group order_list = [] for surface in self.surfaces: order_list.append(surface['name'] + 'group') order_list.append('vlmstates') for surface in self.surfaces: order_list.append(surface['name'] + 'loads') coupled.set_order(order_list) # Add the coupled group to the root problem root.add('coupled', coupled, promotes=['*']) # Add problem information as an independent variables component prob_vars = [('v', self.prob_dict['v']), ('alpha', self.prob_dict['alpha']), ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']), ('rho', self.prob_dict['rho'])] root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*']) # Add functionals to evaluate performance of the system root.add('fuelburn', FunctionalBreguetRange(self.surfaces, self.prob_dict), promotes=['*']) root.add('eq_con', FunctionalEquilibrium(self.surfaces, self.prob_dict), promotes=['*']) self.setup_prob()
def setup_aero(self): """ Specific method to add the necessary components to the problem for an aerodynamic problem. """ # Set the problem name if the user doesn't if 'prob_name' not in self.prob_dict.keys(): self.prob_dict['prob_name'] = 'aero' # Create the base root-level group root = Group() # Create the problem and assign the root group self.prob = Problem() self.prob.root = root # Loop over each surface in the surfaces list for surface in self.surfaces: # Get the surface name and create a group to contain components # only for this surface name = surface['name'] tmp_group = Group() # Add independent variables that do not belong to a specific component indep_vars = [(name + 'twist_cp', numpy.zeros(surface['num_twist'])), (name + 'dihedral', surface['dihedral']), (name + 'sweep', surface['sweep']), (name + 'span', surface['span']), (name + 'taper', surface['taper']), (name + 'disp', numpy.zeros((surface['num_y'], 6)))] # Obtain the Jacobian to interpolate the data from the b-spline # control points jac_twist = get_bspline_mtx(surface['num_twist'], surface['num_y']) # Add aero components to the surface-specific group tmp_group.add('indep_vars', IndepVarComp(indep_vars), promotes=['*']) tmp_group.add('twist_bsp', Bspline(name + 'twist_cp', name + 'twist', jac_twist), promotes=['*']) tmp_group.add('mesh', GeometryMesh(surface), promotes=['*']) tmp_group.add('def_mesh', TransferDisplacements(surface), promotes=['*']) tmp_group.add('vlmgeom', VLMGeometry(surface), promotes=['*']) # Add tmp_group to the problem with the name of the surface and # '_pre_solve' appended. # Note that is a '_pre_solve' and '_post_solve' group for each # individual surface. name_orig = name.strip('_') name = name_orig + '_pre_solve' exec(name + ' = tmp_group') exec('root.add("' + name + '", ' + name + ', promotes=["*"])') # Add a '_post_solve' group name = name_orig + '_post_solve' exec('root.add("' + name + '", ' + 'VLMFunctionals(surface)' + ', promotes=["*"])') # Add problem information as an independent variables component prob_vars = [('v', self.prob_dict['v']), ('alpha', self.prob_dict['alpha']), ('M', self.prob_dict['M']), ('Re', self.prob_dict['Re']), ('rho', self.prob_dict['rho'])] root.add('prob_vars', IndepVarComp(prob_vars), promotes=['*']) # Add a single 'VLMStates' component that solves for the circulations # and forces from all the surfaces. # While other components only depends on a single surface, # this component requires information from all surfaces because # each surface interacts with the others. root.add('vlmstates', VLMStates(self.surfaces, self.prob_dict), promotes=['*']) self.setup_prob()
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
tot_panels = 0 for surface in OAS_prob.surfaces: ny = surface['num_y'] nx = surface['num_x'] tot_panels += (nx - 1) * (ny - 1) OAS_prob.prob_dict.update({'tot_panels': tot_panels}) # Assume we are only using a single lifting surface for now surface = OAS_prob.surfaces[0] # Initialize the OpenAeroStruct components and save them in a component dictionary comp_dict = {} comp_dict['MaterialsTube'] = MaterialsTube(surface) comp_dict['GeometryMesh'] = GeometryMesh(surface) comp_dict['TransferDisplacements'] = TransferDisplacements(surface) comp_dict['VLMGeometry'] = VLMGeometry(surface) comp_dict['AssembleAIC'] = AssembleAIC([surface]) comp_dict['AeroCirculations'] = AeroCirculations(OAS_prob.prob_dict['tot_panels']) comp_dict['VLMForces'] = VLMForces([surface]) comp_dict['TransferLoads'] = TransferLoads(surface) comp_dict['ComputeNodes'] = ComputeNodes(surface) comp_dict['AssembleK'] = AssembleK(surface) comp_dict['SpatialBeamFEM'] = SpatialBeamFEM(surface['FEMsize']) comp_dict['SpatialBeamDisp'] = SpatialBeamDisp(surface) OAS_prob.comp_dict = comp_dict <<<<<<< HEAD # return the surfaces list, problem dict, and component dict surfaces = [surface] prob_dict = OAS_prob.prob_dict # return surfaces, prob_dict, comp_dict