def generate_naca_camber(M=0, P=0): """ Warnings: This function is now located in sharpy.utils.geo_utils Defines the x and y coordinates of a 4-digit NACA profile's camber line (i.e no thickness). The NACA 4-series airfoils follow the nomenclature: NACA MPTT where: * M indicates the maximum camber :math:`M = 100m` * P indicates the position of the maximum camber :math:`P=10p` * TT indicates the thickness to chord ratio :math:`TT=(t/c)*100` Args: M (float): maximum camber times 100 (i.e. the first of the 4 digits) P (float): position of the maximum camber times 10 (i.e. the second of the 4 digits) Returns: (x_vec,y_vec): ``x`` and ``y`` coordinates of the chosen airfoil Example: The NACA2400 airfoil would have 2% camber with the maximum at 40% of the chord and 0 thickness. To plot the camber line one would use this function as: ``x_vec, y_vec = generate_naca_camber(M = 2, P = 4)`` """ warnings.warn( 'Deprecated utility function location. Use the one in sharpy.utils.geo_utils instead', stacklevel=2) x_vec, y_vec = new_geo_utils.generate_naca_camber(M, P) # m = M * 1e-2 # p = P * 1e-1 # # def naca(x, m, p): # if x < 1e-6: # return 0.0 # elif x < p: # return m / (p * p) * (2 * p * x - x * x) # elif x > p and x < 1 + 1e-6: # return m / ((1 - p) * (1 - p)) * (1 - 2 * p + 2 * p * x - x * x) # # x_vec = np.linspace(0, 1, 1000) # y_vec = np.array([naca(x, m, p) for x in x_vec]) return x_vec, y_vec
def generate_aero_file(self, route=None, case_name=None): """ Generates the ``.aero.h5`` file with the aerodynamic properties of the wing Args: route (str): route to write case file. If None is specified the default will be used case_name (str): name of file. If None is specified the default will be used """ if not route: route = self.case_route if not case_name: case_name = self.case_name if not os.path.isdir(self.case_route): os.makedirs(self.case_route) chord = self.chord twist = self.twist airfoil_distribution = self.airfoil_distribution surface_distribution = self.surface_distribution surface_m = self.surface_m m_distribution = self.m_distribution aero_nodes = self.aero_nodes elastic_axis = self.elastic_axis control_surface = self.control_surface control_surface_deflection = self.control_surface_deflection control_surface_chord = self.control_surface_chord control_surface_hinge_coord = self.control_surface_hinge_coord control_surface_type = self.control_surface_type control_surface_deflection[0] = self.cs_deflection with h5.File(route + '/' + case_name + '.aero.h5', 'a') as h5file: airfoils_group = h5file.create_group('airfoils') # add one airfoil naca_airfoil_main = airfoils_group.create_dataset( '0', data=np.column_stack(geo_utils.generate_naca_camber(P=0, M=0))) naca_airfoil_tail = airfoils_group.create_dataset( '1', data=np.column_stack(geo_utils.generate_naca_camber(P=0, M=0))) naca_airfoil_fin = airfoils_group.create_dataset( '2', data=np.column_stack(geo_utils.generate_naca_camber(P=0, M=0))) # chord chord_input = h5file.create_dataset('chord', data=chord) dim_attr = chord_input.attrs['units'] = 'm' # twist twist_input = h5file.create_dataset('twist', data=twist) dim_attr = twist_input.attrs['units'] = 'rad' # airfoil distribution airfoil_distribution_input = h5file.create_dataset( 'airfoil_distribution', data=airfoil_distribution) surface_distribution_input = h5file.create_dataset( 'surface_distribution', data=surface_distribution) surface_m_input = h5file.create_dataset('surface_m', data=surface_m) m_distribution_input = h5file.create_dataset( 'm_distribution', data=m_distribution.encode('ascii', 'ignore')) aero_node_input = h5file.create_dataset('aero_node', data=aero_nodes) elastic_axis_input = h5file.create_dataset('elastic_axis', data=elastic_axis) control_surface_input = h5file.create_dataset('control_surface', data=control_surface) control_surface_deflection_input = h5file.create_dataset( 'control_surface_deflection', data=control_surface_deflection) control_surface_chord_input = h5file.create_dataset( 'control_surface_chord', data=control_surface_chord) control_surface_hinge_coord_input = h5file.create_dataset( 'control_surface_hinge_coord', data=control_surface_hinge_coord) control_surface_types_input = h5file.create_dataset( 'control_surface_type', data=control_surface_type)
def update_aero_prop(self): assert hasattr(self,'conn_glob'),\ 'Run "update_derived_params" before generating files' num_nodes_elem = self.num_nodes_elem num_elem_vtp = self.num_elem_vtp num_elem_htpL = self.num_elem_htpL num_elem_htpR = self.num_elem_htpR num_elem_tot = self.num_elem_tot num_nodes_vtp = self.num_nodes_vtp num_nodes_htpL = self.num_nodes_htpL num_nodes_htpR = self.num_nodes_htpR num_nodes_tot = self.num_nodes_tot ### Generate aerofoil profiles. # only flat plate airfoil_distribution = np.zeros((num_elem_tot, 3), dtype=np.int) Airfoils_surf = [] Airfoils_surf.append( np.column_stack(geo_utils.generate_naca_camber(0, 2))) # # vtp # # Airfoils_surf.append(geo_utils.generate_naca_camber(0,2)) # # Na=1 # for ee in self.conn_surf_vtp: # for nn_loc in [0,2]: # node_glob=self.conn_glob[ee,nn_loc] # eta=xxx # Airfoils_surf.append( # np.column_stack( # geo_utils.interpolate_naca_camber( # eta, # 0,self.root_airfoil_P, # self.tip_airfoil_M,self.tip_airfoil_P))) ### Define aerodynamic nodes aero_node = np.ones((num_nodes_tot, ), dtype=bool) ### Define chord-wise panelling surface_m = self.M * np.ones((3, ), dtype=int) ### Define chord-length, sweep, twist chord = np.zeros((num_elem_tot, 3)) twist = np.zeros((num_elem_tot, 3)) sweep = np.zeros((num_elem_tot, 3)) # vtp nn_count = 0 for ee in self.conn_surf_vtp: for nn in [0, 1, 2]: nn_loc = self.conn_loc[nn] eta = np.float(nn_count + nn) / (num_nodes_vtp - 1) chord[ee, nn_loc] = ( 1. - eta) * self.chord_vtp_root + eta * self.chord_htp_root sweep[ee, nn_loc] = eta * np.pi / 180. * (-self.alpha_htp_deg) nn_count += 2 # htpL twist[self.conn_surf_htpL, :] = -np.pi / 180. * self.alpha_htp_deg nn_count = 0 for ee in self.conn_surf_htpL: for nn in [0, 1, 2]: nn_loc = self.conn_loc[nn] eta = np.float(nn_count + nn) / (num_nodes_htpL - 1) chord[ee, nn_loc] = ( 1. - eta) * self.chord_htp_tip + eta * self.chord_htp_root nn_count += 1 # htpR twist[self.conn_surf_htpR, :] = -np.pi / 180. * self.alpha_htp_deg nn_count = 0 for ee in self.conn_surf_htpR: for nn in [0, 1, 2]: nn_loc = self.conn_loc[nn] eta = np.float(nn_count + nn) / (num_nodes_htpR - 1) chord[ee, nn_loc] = ( 1. - eta) * self.chord_htp_root + eta * self.chord_htp_tip nn_count += 1 ### Define chord elastic axis position elastic_axis = self.main_ea * np.ones(( num_elem_tot, 3, )) ### store self.Airfoils_surf = Airfoils_surf self.airfoil_distribution = airfoil_distribution self.aero_node = aero_node self.surface_m = surface_m self.twist = twist self.sweep = sweep self.chord = chord self.elastic_axis = elastic_axis
def generate(self): n_surfaces = 5 structure = self.structure n_elem = structure.n_elem n_node_elem = structure.n_node_elem n_control_surfaces = 2 n_elem_main = structure.n_elem_main n_node_main = structure.n_node_main m = self.m n_elem_fuselage = structure.n_elem_fuselage n_node_fuselage = structure.n_node_fuselage n_elem_fin = structure.n_elem_fin n_node_fin = structure.n_node_fin n_elem_tail = structure.n_elem_tail n_node_tail = structure.n_node_tail # aero airfoil_distribution = np.zeros( (structure.n_elem, structure.n_node_elem), dtype=int) surface_distribution = np.zeros((structure.n_elem, ), dtype=int) - 1 surface_m = np.zeros((n_surfaces, ), dtype=int) m_distribution = 'uniform' aero_node = np.zeros((structure.n_node, ), dtype=bool) twist = np.zeros((structure.n_elem, structure.n_node_elem)) sweep = np.zeros((structure.n_elem, structure.n_node_elem)) chord = np.zeros(( structure.n_elem, structure.n_node_elem, )) elastic_axis = np.zeros(( structure.n_elem, structure.n_node_elem, )) control_surface = np.zeros((n_elem, n_node_elem), dtype=int) - 1 control_surface_type = np.zeros((n_control_surfaces, ), dtype=int) control_surface_deflection = np.zeros((n_control_surfaces, )) control_surface_chord = np.zeros((n_control_surfaces, ), dtype=int) control_surface_hinge_coord = np.zeros((n_control_surfaces, ), dtype=float) # control surface type 0 = static # control surface type 1 = dynamic control_surface_type[0] = 0 control_surface_deflection[0] = self.cs_deflection control_surface_chord[0] = m control_surface_hinge_coord[ 0] = -0.25 # nondimensional wrt elastic axis (+ towards the trailing edge) control_surface_type[1] = 0 control_surface_deflection[1] = self.rudder_deflection control_surface_chord[1] = m // 2 control_surface_hinge_coord[ 1] = -0. # nondimensional wrt elastic axis (+ towards the trailing edge) we = 0 wn = 0 # right wing (surface 0, beam 0) i_surf = 0 airfoil_distribution[we:we + n_elem_main, :] = 0 surface_distribution[we:we + n_elem_main] = i_surf surface_m[i_surf] = m aero_node[wn:wn + n_node_main] = True temp_chord = np.linspace(chord_main, chord_main, n_node_main) temp_sweep = np.linspace(0.0, 0 * np.pi / 180, n_node_main) node_counter = 0 for i_elem in range(we, we + n_elem_main): for i_local_node in range(n_node_elem): if not i_local_node == 0: node_counter += 1 chord[i_elem, i_local_node] = temp_chord[node_counter] elastic_axis[i_elem, i_local_node] = ea_main sweep[i_elem, i_local_node] = temp_sweep[node_counter] we += n_elem_main wn += n_node_main # left wing (surface 1, beam 1) i_surf = 1 airfoil_distribution[we:we + n_elem_main, :] = 0 # airfoil_distribution[wn:wn + n_node_main - 1] = 0 surface_distribution[we:we + n_elem_main] = i_surf surface_m[i_surf] = m aero_node[wn:wn + n_node_main - 1] = True # chord[wn:wn + num_node_main - 1] = np.linspace(main_chord, main_tip_chord, num_node_main)[1:] # chord[wn:wn + num_node_main - 1] = main_chord # elastic_axis[wn:wn + num_node_main - 1] = main_ea temp_chord = np.linspace(chord_main, chord_main, n_node_main) node_counter = 0 for i_elem in range(we, we + n_elem_main): for i_local_node in range(n_node_elem): if not i_local_node == 0: node_counter += 1 chord[i_elem, i_local_node] = temp_chord[node_counter] elastic_axis[i_elem, i_local_node] = ea_main sweep[i_elem, i_local_node] = -temp_sweep[node_counter] we += n_elem_main wn += n_node_main - 1 we += n_elem_fuselage wn += n_node_fuselage - 1 - 1 # # # fin (surface 2, beam 3) i_surf = 2 airfoil_distribution[we:we + n_elem_fin, :] = 1 # airfoil_distribution[wn:wn + n_node_fin] = 0 surface_distribution[we:we + n_elem_fin] = i_surf surface_m[i_surf] = m aero_node[wn:wn + n_node_fin] = True # chord[wn:wn + num_node_fin] = fin_chord for i_elem in range(we, we + n_elem_fin): for i_local_node in range(n_node_elem): chord[i_elem, i_local_node] = chord_fin elastic_axis[i_elem, i_local_node] = ea_fin control_surface[i_elem, i_local_node] = 1 # twist[end_of_fuselage_node] = 0 # twist[wn:] = 0 # elastic_axis[wn:wn + num_node_main] = fin_ea we += n_elem_fin wn += n_node_fin - 1 control_surface[we - 1, :] = -1 # # # # right tail (surface 3, beam 4) i_surf = 3 airfoil_distribution[we:we + n_elem_tail, :] = 2 # airfoil_distribution[wn:wn + n_node_tail] = 0 surface_distribution[we:we + n_elem_tail] = i_surf surface_m[i_surf] = m # XXX not very elegant aero_node[wn:] = True # chord[wn:wn + num_node_tail] = tail_chord # elastic_axis[wn:wn + num_node_main] = tail_ea for i_elem in range(we, we + n_elem_tail): for i_local_node in range(n_node_elem): twist[i_elem, i_local_node] = -0 for i_elem in range(we, we + n_elem_tail): for i_local_node in range(n_node_elem): chord[i_elem, i_local_node] = chord_tail elastic_axis[i_elem, i_local_node] = ea_tail control_surface[i_elem, i_local_node] = 0 we += n_elem_tail wn += n_node_tail # # # left tail (surface 4, beam 5) i_surf = 4 airfoil_distribution[we:we + n_elem_tail, :] = 2 # airfoil_distribution[wn:wn + n_node_tail - 1] = 0 surface_distribution[we:we + n_elem_tail] = i_surf surface_m[i_surf] = m aero_node[wn:wn + n_node_tail - 1] = True # chord[wn:wn + num_node_tail] = tail_chord # elastic_axis[wn:wn + num_node_main] = tail_ea # twist[we:we + num_elem_tail] = -tail_twist for i_elem in range(we, we + n_elem_tail): for i_local_node in range(n_node_elem): twist[i_elem, i_local_node] = -0 for i_elem in range(we, we + n_elem_tail): for i_local_node in range(n_node_elem): chord[i_elem, i_local_node] = chord_tail elastic_axis[i_elem, i_local_node] = ea_tail control_surface[i_elem, i_local_node] = 0 we += n_elem_tail wn += n_node_tail with h5.File(self.route + '/' + self.case_name + '.aero.h5', 'a') as h5file: airfoils_group = h5file.create_group('airfoils') # add one airfoil naca_airfoil_main = airfoils_group.create_dataset( '0', data=np.column_stack(generate_naca_camber(P=0, M=0))) naca_airfoil_tail = airfoils_group.create_dataset( '1', data=np.column_stack(generate_naca_camber(P=0, M=0))) naca_airfoil_fin = airfoils_group.create_dataset( '2', data=np.column_stack(generate_naca_camber(P=0, M=0))) # chord chord_input = h5file.create_dataset('chord', data=chord) dim_attr = chord_input.attrs['units'] = 'm' # twist twist_input = h5file.create_dataset('twist', data=twist) dim_attr = twist_input.attrs['units'] = 'rad' # sweep sweep_input = h5file.create_dataset('sweep', data=sweep) dim_attr = sweep_input.attrs['units'] = 'rad' # airfoil distribution airfoil_distribution_input = h5file.create_dataset( 'airfoil_distribution', data=airfoil_distribution) surface_distribution_input = h5file.create_dataset( 'surface_distribution', data=surface_distribution) surface_m_input = h5file.create_dataset('surface_m', data=surface_m) m_distribution_input = h5file.create_dataset( 'm_distribution', data=m_distribution.encode('ascii', 'ignore')) aero_node_input = h5file.create_dataset('aero_node', data=aero_node) elastic_axis_input = h5file.create_dataset('elastic_axis', data=elastic_axis) control_surface_input = h5file.create_dataset('control_surface', data=control_surface) control_surface_deflection_input = h5file.create_dataset( 'control_surface_deflection', data=control_surface_deflection) control_surface_chord_input = h5file.create_dataset( 'control_surface_chord', data=control_surface_chord) control_surface_hinge_coord_input = h5file.create_dataset( 'control_surface_hinge_coord', data=control_surface_hinge_coord) control_surface_types_input = h5file.create_dataset( 'control_surface_type', data=control_surface_type) if self.polars is not None: polars_group = h5file.create_group('polars') for i_airfoil in range(3): # there are three airfoils polars_group.create_dataset('{:g}'.format(i_airfoil), data=self.polars)