def load_uvlm(filename): import sharpy.utils.h5utils as h5 cout.cout_wrap('Loading UVLM state space system projected onto structural DOFs from file') read_data = h5.readh5(filename).ss # uvlm_ss_read = read_data.linear.linear_system.uvlm.ss uvlm_ss_read = read_data return libss.ss(uvlm_ss_read.A, uvlm_ss_read.B, uvlm_ss_read.C, uvlm_ss_read.D, dt=uvlm_ss_read.dt)
def load_tangent_vectors(self): tangent_file = self.settings['tangent_input_file'] if tangent_file: tangents = h5.readh5(tangent_file) right_tangent = tangents.right_tangent left_tangent = tangents.left_tangent rc = tangents.rc ro = tangents.ro fc = tangents.fc fo = tangents.fo else: left_tangent = None right_tangent = None return left_tangent, right_tangent, rc, ro, fc, fo
def setUp(self): # select test case fname = os.path.dirname( os.path.abspath(__file__) ) + '/h5input/goland_mod_Nsurf01_M003_N004_a040.aero_state.h5' haero = h5utils.readh5(fname) tsdata = haero.ts00000 # # Rotating cases # fname = './basic_rotating_wing/basic_wing.data.h5' # haero = h5utils.readh5(fname) # tsdata = haero.data.aero.timestep_info[-1] # tsdata.omega = [] # for ss in range(haero.data.aero.n_surf): # tsdata.omega.append(haero.data.structure.timestep_info[-1].for_vel[3:6]) MS = multisurfaces.MultiAeroGridSurfaces(tsdata) MS.get_normal_ind_velocities_at_collocation_points() MS.verify_non_penetration() MS.verify_aic_coll() MS.get_joukovski_qs() MS.verify_joukovski_qs() self.MS = MS
def rotor_from_excel_type03(in_op_params, in_geom_params, in_excel_description, in_options): """ generate_from_excel_type03_db Function needed to generate a wind turbine from an excel database type03 Args: op_param (dict): Dictionary with operating parameters geom_param (dict): Dictionray with geometical parameters excel_description (dict): Dictionary describing the sheets of the excel file option (dict): Dictionary with the different options for the wind turbine generation Returns: rotor (sharpy.utils.generate_cases.AeroelasticInfromation): Aeroelastic information of the rotor """ # Default values op_params = {} op_params['rotation_velocity'] = None # Rotation velocity of the rotor op_params['pitch_deg'] = None # pitch angle in degrees op_params[ 'wsp'] = 0. # wind speed (It may be needed for discretisation purposes) op_params[ 'dt'] = 0. # time step (It may be needed for discretisation purposes) geom_params = {} geom_params[ 'chord_panels'] = None # Number of panels on the blade surface in the chord direction geom_params[ 'tol_remove_points'] = 1e-3 # maximum distance to remove adjacent points geom_params[ 'n_points_camber'] = 100 # number of points to define the camber of the airfoil geom_params[ 'h5_cross_sec_prop'] = None # h5 containing mass and stiffness matrices along the blade geom_params['m_distribution'] = 'uniform' # options = {} options[ 'camber_effect_on_twist'] = False # When true plain airfoils are used and the blade is twisted and preloaded based on thin airfoil theory options[ 'user_defined_m_distribution_type'] = None # type of distribution of the chordwise panels when 'm_distribution' == 'user_defined' options['include_polars'] = False # excel_description = {} excel_description['excel_file_name'] = 'database_excel_type02.xlsx' excel_description['excel_sheet_parameters'] = 'parameters' excel_description['excel_sheet_structural_blade'] = 'structural_blade' excel_description[ 'excel_sheet_discretization_blade'] = 'discretization_blade' excel_description['excel_sheet_aero_blade'] = 'aero_blade' excel_description['excel_sheet_airfoil_info'] = 'airfoil_info' excel_description['excel_sheet_airfoil_chord'] = 'airfoil_coord' # Overwrite the default values with the values of the input arguments for key in in_op_params: op_params[key] = in_op_params[key] for key in in_geom_params: geom_params[key] = in_geom_params[key] for key in in_options: options[key] = in_options[key] for key in in_excel_description: excel_description[key] = in_excel_description[key] # Put the dictionaries information into variables (to avoid changing the function) rotation_velocity = op_params['rotation_velocity'] pitch_deg = op_params['pitch_deg'] wsp = op_params['wsp'] dt = op_params['dt'] chord_panels = geom_params['chord_panels'] tol_remove_points = geom_params['tol_remove_points'] n_points_camber = geom_params['n_points_camber'] h5_cross_sec_prop = geom_params['h5_cross_sec_prop'] m_distribution = geom_params['m_distribution'] camber_effect_on_twist = options['camber_effect_on_twist'] user_defined_m_distribution_type = options[ 'user_defined_m_distribution_type'] include_polars = options['include_polars'] excel_file_name = excel_description['excel_file_name'] excel_sheet_parameters = excel_description['excel_sheet_parameters'] excel_sheet_structural_blade = excel_description[ 'excel_sheet_structural_blade'] excel_sheet_discretization_blade = excel_description[ 'excel_sheet_discretization_blade'] excel_sheet_aero_blade = excel_description['excel_sheet_aero_blade'] excel_sheet_airfoil_info = excel_description['excel_sheet_airfoil_info'] excel_sheet_airfoil_coord = excel_description['excel_sheet_airfoil_chord'] ###################################################################### ## BLADE ###################################################################### blade = gc.AeroelasticInformation() ###################################################################### ### STRUCTURE ###################################################################### # Read blade structural information from excel file rR_structural = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'rR') OutPElAxis = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'OutPElAxis') InPElAxis = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'InPElAxis') ElAxisAftLEc = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'ElAxisAftLEc') StrcTwst = gc.read_column_sheet_type01( excel_file_name, excel_sheet_structural_blade, 'StrcTwst') * deg2rad BMassDen = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'BMassDen') FlpStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlpStff') EdgStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'EdgStff') FlapEdgeStiff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlapEdgeStiff') GJStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'GJStff') EAStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'EAStff') FlpIner = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlpIner') EdgIner = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'EdgIner') FlapEdgeIner = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlapEdgeIner') PrebendRef = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'PrebendRef') PreswpRef = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'PreswpRef') OutPcg = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'OutPcg') InPcg = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'InPcg') # Blade parameters TipRad = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'TipRad') # HubRad = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'HubRad') # Discretization points rR = gc.read_column_sheet_type01(excel_file_name, excel_sheet_discretization_blade, 'rR') # Interpolate excel variables into the correct locations # Geometry if rR[0] < rR_structural[0]: rR_structural = np.concatenate((np.array([0.]), rR_structural), ) OutPElAxis = np.concatenate((np.array([OutPElAxis[0]]), OutPElAxis), ) InPElAxis = np.concatenate((np.array([InPElAxis[0]]), InPElAxis), ) ElAxisAftLEc = np.concatenate( (np.array([ElAxisAftLEc[0]]), ElAxisAftLEc), ) StrcTwst = np.concatenate((np.array([StrcTwst[0]]), StrcTwst), ) BMassDen = np.concatenate((np.array([BMassDen[0]]), BMassDen), ) FlpStff = np.concatenate((np.array([FlpStff[0]]), FlpStff), ) EdgStff = np.concatenate((np.array([EdgStff[0]]), EdgStff), ) FlapEdgeStiff = np.concatenate( (np.array([FlapEdgeStiff[0]]), FlapEdgeStiff), ) GJStff = np.concatenate((np.array([GJStff[0]]), GJStff), ) EAStff = np.concatenate((np.array([EAStff[0]]), EAStff), ) FlpIner = np.concatenate((np.array([FlpIner[0]]), FlpIner), ) EdgIner = np.concatenate((np.array([EdgIner[0]]), EdgIner), ) FlapEdgeIner = np.concatenate( (np.array([FlapEdgeIner[0]]), FlapEdgeIner), ) PrebendRef = np.concatenate((np.array([PrebendRef[0]]), PrebendRef), ) PreswpRef = np.concatenate((np.array([PreswpRef[0]]), PreswpRef), ) OutPcg = np.concatenate((np.array([OutPcg[0]]), OutPcg), ) InPcg = np.concatenate((np.array([InPcg[0]]), InPcg), ) # Base parameters use_excel_struct_as_elem = False if use_excel_struct_as_elem: blade.StructuralInformation.num_node_elem = 3 blade.StructuralInformation.num_elem = len(rR) - 2 blade.StructuralInformation.compute_basic_num_node() node_r, elem_r = create_node_radial_pos_from_elem_centres( rR * TipRad, blade.StructuralInformation.num_node, blade.StructuralInformation.num_elem, blade.StructuralInformation.num_node_elem) else: # Use excel struct as nodes # Check the number of nodes blade.StructuralInformation.num_node_elem = 3 blade.StructuralInformation.num_node = len(rR) if ((len(rR) - 1) % (blade.StructuralInformation.num_node_elem - 1)) == 0: blade.StructuralInformation.num_elem = int( (len(rR) - 1) / (blade.StructuralInformation.num_node_elem - 1)) node_r = rR * TipRad elem_rR = rR[1::2] + 0. elem_r = rR[1::2] * TipRad + 0. else: raise RuntimeError( ("ERROR: Cannot build %d-noded elements from %d nodes" % (blade.StructuralInformation.num_node_elem, blade.StructuralInformation.num_node))) node_y = np.interp(rR, rR_structural, InPElAxis) + np.interp( rR, rR_structural, PreswpRef) node_z = -np.interp(rR, rR_structural, OutPElAxis) - np.interp( rR, rR_structural, PrebendRef) node_twist = -1.0 * np.interp(rR, rR_structural, StrcTwst) coordinates = create_blade_coordinates( blade.StructuralInformation.num_node, node_r, node_y, node_z) if h5_cross_sec_prop is None: # Stiffness elem_EA = np.interp(elem_rR, rR_structural, EAStff) elem_EIy = np.interp(elem_rR, rR_structural, FlpStff) elem_EIz = np.interp(elem_rR, rR_structural, EdgStff) elem_EIyz = np.interp(elem_rR, rR_structural, FlapEdgeStiff) elem_GJ = np.interp(elem_rR, rR_structural, GJStff) # Stiffness: estimate unknown properties cout.cout_wrap.print_file = False cout.cout_wrap( 'WARNING: The poisson cofficient is assumed equal to 0.3', 3) cout.cout_wrap('WARNING: Cross-section area is used as shear area', 3) poisson_coef = 0.3 elem_GAy = elem_EA / 2.0 / (1.0 + poisson_coef) elem_GAz = elem_EA / 2.0 / (1.0 + poisson_coef) # Inertia elem_pos_cg_B = np.zeros((blade.StructuralInformation.num_elem, 3), ) elem_pos_cg_B[:, 1] = np.interp(elem_rR, rR_structural, InPcg) elem_pos_cg_B[:, 2] = -np.interp(elem_rR, rR_structural, OutPcg) elem_mass_per_unit_length = np.interp(elem_rR, rR_structural, BMassDen) elem_mass_iner_y = np.interp(elem_rR, rR_structural, FlpIner) elem_mass_iner_z = np.interp(elem_rR, rR_structural, EdgIner) elem_mass_iner_yz = np.interp(elem_rR, rR_structural, FlapEdgeIner) # Inertia: estimate unknown properties cout.cout_wrap( 'WARNING: Using perpendicular axis theorem to compute the inertia around xB', 3) elem_mass_iner_x = elem_mass_iner_y + elem_mass_iner_z # Generate blade structural properties blade.StructuralInformation.create_mass_db_from_vector( elem_mass_per_unit_length, elem_mass_iner_x, elem_mass_iner_y, elem_mass_iner_z, elem_pos_cg_B, elem_mass_iner_yz) blade.StructuralInformation.create_stiff_db_from_vector( elem_EA, elem_GAy, elem_GAz, elem_GJ, elem_EIy, elem_EIz, elem_EIyz) else: # read Mass/Stiffness from database cross_prop = h5.readh5(h5_cross_sec_prop).str_prop # create mass_db/stiffness_db (interpolate at mid-node of each element) blade.StructuralInformation.mass_db = scint.interp1d( cross_prop.radius, cross_prop.M, kind='cubic', copy=False, assume_sorted=True, axis=0, bounds_error=False, fill_value='extrapolate')(node_r[1::2]) blade.StructuralInformation.stiffness_db = scint.interp1d( cross_prop.radius, cross_prop.K, kind='cubic', copy=False, assume_sorted=True, axis=0, bounds_error=False, fill_value='extrapolate')(node_r[1::2]) blade.StructuralInformation.generate_1to1_from_vectors( num_node_elem=blade.StructuralInformation.num_node_elem, num_node=blade.StructuralInformation.num_node, num_elem=blade.StructuralInformation.num_elem, coordinates=coordinates, stiffness_db=blade.StructuralInformation.stiffness_db, mass_db=blade.StructuralInformation.mass_db, frame_of_reference_delta='y_AFoR', vec_node_structural_twist=node_twist, num_lumped_mass=0) # Boundary conditions blade.StructuralInformation.boundary_conditions = np.zeros( (blade.StructuralInformation.num_node), dtype=int) blade.StructuralInformation.boundary_conditions[0] = 1 blade.StructuralInformation.boundary_conditions[-1] = -1 ###################################################################### ### AERODYNAMICS ###################################################################### # Read blade aerodynamic information from excel file rR_aero = gc.read_column_sheet_type01(excel_file_name, excel_sheet_aero_blade, 'rR') chord_aero = gc.read_column_sheet_type01(excel_file_name, excel_sheet_aero_blade, 'BlChord') thickness_aero = gc.read_column_sheet_type01(excel_file_name, excel_sheet_aero_blade, 'BlThickness') pure_airfoils_names = gc.read_column_sheet_type01( excel_file_name, excel_sheet_airfoil_info, 'Name') pure_airfoils_thickness = gc.read_column_sheet_type01( excel_file_name, excel_sheet_airfoil_info, 'Thickness') node_ElAxisAftLEc = np.interp(node_r, rR_structural * TipRad, ElAxisAftLEc) # Read coordinates of the pure airfoils n_pure_airfoils = len(pure_airfoils_names) pure_airfoils_camber = np.zeros((n_pure_airfoils, n_points_camber, 2), ) xls = pd.ExcelFile(excel_file_name) excel_db = pd.read_excel(xls, sheet_name=excel_sheet_airfoil_coord) for iairfoil in range(n_pure_airfoils): # Look for the NaN icoord = 2 while (not (math.isnan( excel_db["%s_x" % pure_airfoils_names[iairfoil]][icoord]))): icoord += 1 if (icoord == len(excel_db["%s_x" % pure_airfoils_names[iairfoil]])): break # Compute the camber of the airfoils at the defined chord points pure_airfoils_camber[iairfoil, :, 0], pure_airfoils_camber[ iairfoil, :, 1] = gc.get_airfoil_camber( excel_db["%s_x" % pure_airfoils_names[iairfoil]][2:icoord], excel_db["%s_y" % pure_airfoils_names[iairfoil]][2:icoord], n_points_camber) # Basic variables surface_distribution = np.zeros((blade.StructuralInformation.num_elem), dtype=int) # Interpolate in the correct positions node_chord = np.interp(node_r, rR_aero * TipRad, chord_aero) # Define the nodes with aerodynamic properties # Look for the first element that is goint to be aerodynamic first_aero_elem = 0 while (elem_r[first_aero_elem] <= rR_aero[0] * TipRad): first_aero_elem += 1 first_aero_node = first_aero_elem * ( blade.StructuralInformation.num_node_elem - 1) aero_node = np.zeros((blade.StructuralInformation.num_node, ), dtype=bool) aero_node[first_aero_node:] = np.ones( (blade.StructuralInformation.num_node - first_aero_node, ), dtype=bool) # Define the airfoil at each stage # airfoils = blade.AerodynamicInformation.interpolate_airfoils_camber(pure_airfoils_camber,excel_aero_r, node_r, n_points_camber) node_thickness = np.interp(node_r, rR_aero * TipRad, thickness_aero) airfoils = blade.AerodynamicInformation.interpolate_airfoils_camber_thickness( pure_airfoils_camber, pure_airfoils_thickness, node_thickness, n_points_camber) airfoil_distribution = np.linspace(0, blade.StructuralInformation.num_node - 1, blade.StructuralInformation.num_node, dtype=int) # User defined m distribution if (m_distribution == 'user_defined') and (user_defined_m_distribution_type == 'last_geometric'): blade_nodes = blade.StructuralInformation.num_node udmd_by_nodes = np.zeros((blade_nodes, chord_panels[0] + 1)) for inode in range(blade_nodes): r = np.linalg.norm( blade.StructuralInformation.coordinates[inode, :]) vrel = np.sqrt(rotation_velocity**2 * r**2 + wsp**2) last_length = vrel * dt / node_chord[inode] last_length = np.minimum(last_length, 0.5) if last_length <= 0.5: ratio = gc.get_factor_geometric_progression( last_length, 1., chord_panels) udmd_by_nodes[inode, -1] = 1. udmd_by_nodes[inode, 0] = 0. for im in range(chord_panels[0] - 1, 0, -1): udmd_by_nodes[inode, im] = udmd_by_nodes[inode, im + 1] - last_length last_length *= ratio # Check if (np.diff(udmd_by_nodes[inode, :]) < 0.).any(): sys.error( "ERROR in the panel discretization of the blade in node %d" % (inode)) else: raise RuntimeError( ("ERROR: cannot match the last panel size for node: %d" % inode)) udmd_by_nodes[inode, :] = np.linspace(0, 1, chord_panels + 1) else: udmd_by_nodes = None node_twist = np.zeros_like(node_chord) if camber_effect_on_twist: cout.cout_wrap( "WARNING: The steady applied Mx should be manually multiplied by the density", 3) for inode in range(blade.StructuralInformation.num_node): node_twist[inode] = gc.get_aoacl0_from_camber( airfoils[inode, :, 0], airfoils[inode, :, 1]) mu0 = gc.get_mu0_from_camber(airfoils[inode, :, 0], airfoils[inode, :, 1]) r = np.linalg.norm( blade.StructuralInformation.coordinates[inode, :]) vrel = np.sqrt(rotation_velocity**2 * r**2 + wsp**2) if inode == 0: dr = 0.5 * np.linalg.norm( blade.StructuralInformation.coordinates[1, :] - blade.StructuralInformation.coordinates[0, :]) elif inode == len(blade.StructuralInformation.coordinates[:, 0]) - 1: dr = 0.5 * np.linalg.norm( blade.StructuralInformation.coordinates[-1, :] - blade.StructuralInformation.coordinates[-2, :]) else: dr = 0.5 * np.linalg.norm( blade.StructuralInformation.coordinates[inode + 1, :] - blade.StructuralInformation.coordinates[inode - 1, :]) moment_factor = 0.5 * vrel**2 * node_chord[inode]**2 * dr # print("node", inode, "mu0", mu0, "CMc/4", 2.*mu0 + np.pi/2*node_twist[inode]) blade.StructuralInformation.app_forces[ inode, 3] = (2. * mu0 + np.pi / 2 * node_twist[inode]) * moment_factor airfoils[inode, :, 1] *= 0. # Write SHARPy format blade.AerodynamicInformation.create_aerodynamics_from_vec( blade.StructuralInformation, aero_node, node_chord, node_twist, np.pi * np.ones_like(node_chord), chord_panels, surface_distribution, m_distribution, node_ElAxisAftLEc, airfoil_distribution, airfoils, udmd_by_nodes) # Read the polars of the pure airfoils if include_polars: pure_polars = [None] * n_pure_airfoils for iairfoil in range(n_pure_airfoils): excel_sheet_polar = pure_airfoils_names[iairfoil] aoa = gc.read_column_sheet_type01(excel_file_name, excel_sheet_polar, 'AoA') cl = gc.read_column_sheet_type01(excel_file_name, excel_sheet_polar, 'CL') cd = gc.read_column_sheet_type01(excel_file_name, excel_sheet_polar, 'CD') cm = gc.read_column_sheet_type01(excel_file_name, excel_sheet_polar, 'CM') polar = ap.polar() polar.initialise(np.column_stack((aoa, cl, cd, cm))) pure_polars[iairfoil] = polar # Generate the polars for each airfoil blade.AerodynamicInformation.polars = [ None ] * blade.StructuralInformation.num_node for inode in range(blade.StructuralInformation.num_node): # Find the airfoils between which the node is; ipure = 0 while pure_airfoils_thickness[ipure] > node_thickness[inode]: ipure += 1 if (ipure == n_pure_airfoils): ipure -= 1 break coef = (node_thickness[inode] - pure_airfoils_thickness[ipure - 1] ) / (pure_airfoils_thickness[ipure] - pure_airfoils_thickness[ipure - 1]) polar = ap.interpolate(pure_polars[ipure - 1], pure_polars[ipure], coef) blade.AerodynamicInformation.polars[inode] = polar.table ###################################################################### ## ROTOR ###################################################################### # Read from excel file numberOfBlades = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'NumBl') tilt = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'ShftTilt') * deg2rad cone = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'Cone') * deg2rad # pitch = gc.read_column_sheet_type01(excel_file_name, excel_sheet_rotor, 'Pitch')*deg2rad # Apply pitch blade.StructuralInformation.rotate_around_origin(np.array([1., 0., 0.]), -pitch_deg * deg2rad) # Apply coning blade.StructuralInformation.rotate_around_origin(np.array([0., 1., 0.]), -cone) # Build the whole rotor rotor = blade.copy() for iblade in range(numberOfBlades - 1): blade2 = blade.copy() blade2.StructuralInformation.rotate_around_origin( np.array([0., 0., 1.]), (iblade + 1) * (360.0 / numberOfBlades) * deg2rad) rotor.assembly(blade2) blade2 = None rotor.remove_duplicated_points(tol_remove_points) # Apply tilt rotor.StructuralInformation.rotate_around_origin(np.array([0., 1., 0.]), tilt) return rotor
def rotor_from_excel_type02( chord_panels, rotation_velocity, pitch_deg, excel_file_name='database_excel_type02.xlsx', excel_sheet_parameters='parameters', excel_sheet_structural_blade='structural_blade', excel_sheet_discretization_blade='discretization_blade', excel_sheet_aero_blade='aero_blade', excel_sheet_airfoil_info='airfoil_info', excel_sheet_airfoil_coord='airfoil_coord', m_distribution='uniform', h5_cross_sec_prop=None, n_points_camber=100, tol_remove_points=1e-3, user_defined_m_distribution_type=None, camber_effect_on_twist=False, wsp=0., dt=0.): """ generate_from_excel_type02_db Function needed to generate a wind turbine from an excel database type02 Args: chord_panels (int): Number of panels on the blade surface in the chord direction rotation_velocity (float): Rotation velocity of the rotor pitch_deg (float): pitch angle in degrees excel_file_name (str): excel_sheet_structural_blade (str): excel_sheet_discretization_blade (str): excel_sheet_aero_blade (str): excel_sheet_airfoil_info (str): excel_sheet_airfoil_coord (str): excel_sheet_parameters (str): h5_cross_sec_prop (str): h5 containing mass and stiffness matrices along the blade. m_distribution (str): n_points_camber (int): number of points to define the camber of the airfoil, tol_remove_points (float): maximum distance to remove adjacent points user_defined_m_distribution_type (string): type of distribution of the chordwise panels when 'm_distribution' == 'user_defined' camber_effects_on_twist (bool): When true plain airfoils are used and the blade is twisted and preloaded based on thin airfoil theory wsp (float): wind speed (It may be needed for discretisation purposes) dt (float): time step (It may be needed for discretisation purposes) Returns: rotor (sharpy.utils.generate_cases.AeroelasticInfromation): Aeroelastic information of the rotor Note: - h5_cross_sec_prop is a path to a h5 containing the following groups: - str_prop: with: - K: list of 6x6 stiffness matrices - M: list of 6x6 mass matrices - radius: radial location (including hub) of K and M matrices - when h5_cross_sec_prop is not None, mass and stiffness properties are interpolated at BlFract location specified in "excel_sheet_structural_blade" """ ###################################################################### ## BLADE ###################################################################### blade = gc.AeroelasticInformation() ###################################################################### ### STRUCTURE ###################################################################### # Read blade structural information from excel file rR_structural = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'rR') OutPElAxis = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'OutPElAxis') InPElAxis = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'InPElAxis') ElAxisAftLEc = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'ElAxisAftLEc') StrcTwst = gc.read_column_sheet_type01( excel_file_name, excel_sheet_structural_blade, 'StrcTwst') * deg2rad BMassDen = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'BMassDen') FlpStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlpStff') EdgStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'EdgStff') FlapEdgeStiff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlapEdgeStiff') GJStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'GJStff') EAStff = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'EAStff') FlpIner = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlpIner') EdgIner = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'EdgIner') FlapEdgeIner = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'FlapEdgeIner') PrebendRef = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'PrebendRef') PreswpRef = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'PreswpRef') OutPcg = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'OutPcg') InPcg = gc.read_column_sheet_type01(excel_file_name, excel_sheet_structural_blade, 'InPcg') # Blade parameters TipRad = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'TipRad') # HubRad = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'HubRad') # Discretization points rR = gc.read_column_sheet_type01(excel_file_name, excel_sheet_discretization_blade, 'rR') # Interpolate excel variables into the correct locations # Geometry if rR[0] < rR_structural[0]: rR_structural = np.concatenate((np.array([0.]), rR_structural), ) OutPElAxis = np.concatenate((np.array([OutPElAxis[0]]), OutPElAxis), ) InPElAxis = np.concatenate((np.array([InPElAxis[0]]), InPElAxis), ) ElAxisAftLEc = np.concatenate( (np.array([ElAxisAftLEc[0]]), ElAxisAftLEc), ) StrcTwst = np.concatenate((np.array([StrcTwst[0]]), StrcTwst), ) BMassDen = np.concatenate((np.array([BMassDen[0]]), BMassDen), ) FlpStff = np.concatenate((np.array([FlpStff[0]]), FlpStff), ) EdgStff = np.concatenate((np.array([EdgStff[0]]), EdgStff), ) FlapEdgeStiff = np.concatenate( (np.array([FlapEdgeStiff[0]]), FlapEdgeStiff), ) GJStff = np.concatenate((np.array([GJStff[0]]), GJStff), ) EAStff = np.concatenate((np.array([EAStff[0]]), EAStff), ) FlpIner = np.concatenate((np.array([FlpIner[0]]), FlpIner), ) EdgIner = np.concatenate((np.array([EdgIner[0]]), EdgIner), ) FlapEdgeIner = np.concatenate( (np.array([FlapEdgeIner[0]]), FlapEdgeIner), ) PrebendRef = np.concatenate((np.array([PrebendRef[0]]), PrebendRef), ) PreswpRef = np.concatenate((np.array([PreswpRef[0]]), PreswpRef), ) OutPcg = np.concatenate((np.array([OutPcg[0]]), OutPcg), ) InPcg = np.concatenate((np.array([InPcg[0]]), InPcg), ) # Base parameters use_excel_struct_as_elem = False if use_excel_struct_as_elem: blade.StructuralInformation.num_node_elem = 3 blade.StructuralInformation.num_elem = len(rR) - 2 blade.StructuralInformation.compute_basic_num_node() node_r, elem_r = create_node_radial_pos_from_elem_centres( rR * TipRad, blade.StructuralInformation.num_node, blade.StructuralInformation.num_elem, blade.StructuralInformation.num_node_elem) else: # Use excel struct as nodes # Check the number of nodes blade.StructuralInformation.num_node_elem = 3 blade.StructuralInformation.num_node = len(rR) if ((len(rR) - 1) % (blade.StructuralInformation.num_node_elem - 1)) == 0: blade.StructuralInformation.num_elem = int( (len(rR) - 1) / (blade.StructuralInformation.num_node_elem - 1)) node_r = rR * TipRad elem_rR = rR[1::2] + 0. elem_r = rR[1::2] * TipRad + 0. else: print("ERROR: Cannot build ", blade.StructuralInformation.num_node_elem, "-noded elements from ", blade.StructuralInformation.num_node, "nodes") node_y = np.interp(rR, rR_structural, InPElAxis) + np.interp( rR, rR_structural, PreswpRef) node_z = -np.interp(rR, rR_structural, OutPElAxis) - np.interp( rR, rR_structural, PrebendRef) node_twist = -1.0 * np.interp(rR, rR_structural, StrcTwst) coordinates = create_blade_coordinates( blade.StructuralInformation.num_node, node_r, node_y, node_z) if h5_cross_sec_prop is None: # Stiffness elem_EA = np.interp(elem_rR, rR_structural, EAStff) elem_EIy = np.interp(elem_rR, rR_structural, FlpStff) elem_EIz = np.interp(elem_rR, rR_structural, EdgStff) elem_EIyz = np.interp(elem_rR, rR_structural, FlapEdgeStiff) elem_GJ = np.interp(elem_rR, rR_structural, GJStff) # Stiffness: estimate unknown properties print('WARNING: The poisson cofficient is assumed equal to 0.3') print('WARNING: Cross-section area is used as shear area') poisson_coef = 0.3 elem_GAy = elem_EA / 2.0 / (1.0 + poisson_coef) elem_GAz = elem_EA / 2.0 / (1.0 + poisson_coef) # Inertia elem_pos_cg_B = np.zeros((blade.StructuralInformation.num_elem, 3), ) elem_pos_cg_B[:, 1] = np.interp(elem_rR, rR_structural, InPcg) elem_pos_cg_B[:, 2] = -np.interp(elem_rR, rR_structural, OutPcg) elem_mass_per_unit_length = np.interp(elem_rR, rR_structural, BMassDen) elem_mass_iner_y = np.interp(elem_rR, rR_structural, FlpIner) elem_mass_iner_z = np.interp(elem_rR, rR_structural, EdgIner) elem_mass_iner_yz = np.interp(elem_rR, rR_structural, FlapEdgeIner) # Inertia: estimate unknown properties print( 'WARNING: Using perpendicular axis theorem to compute the inertia around xB' ) elem_mass_iner_x = elem_mass_iner_y + elem_mass_iner_z # Generate blade structural properties blade.StructuralInformation.create_mass_db_from_vector( elem_mass_per_unit_length, elem_mass_iner_x, elem_mass_iner_y, elem_mass_iner_z, elem_pos_cg_B, elem_mass_iner_yz) blade.StructuralInformation.create_stiff_db_from_vector( elem_EA, elem_GAy, elem_GAz, elem_GJ, elem_EIy, elem_EIz, elem_EIyz) else: # read Mass/Stiffness from database cross_prop = h5.readh5(h5_cross_sec_prop).str_prop # create mass_db/stiffness_db (interpolate at mid-node of each element) blade.StructuralInformation.mass_db = scint.interp1d( cross_prop.radius, cross_prop.M, kind='cubic', copy=False, assume_sorted=True, axis=0, bounds_error=False, fill_value='extrapolate')(node_r[1::2]) blade.StructuralInformation.stiffness_db = scint.interp1d( cross_prop.radius, cross_prop.K, kind='cubic', copy=False, assume_sorted=True, axis=0, bounds_error=False, fill_value='extrapolate')(node_r[1::2]) blade.StructuralInformation.generate_1to1_from_vectors( num_node_elem=blade.StructuralInformation.num_node_elem, num_node=blade.StructuralInformation.num_node, num_elem=blade.StructuralInformation.num_elem, coordinates=coordinates, stiffness_db=blade.StructuralInformation.stiffness_db, mass_db=blade.StructuralInformation.mass_db, frame_of_reference_delta='y_AFoR', vec_node_structural_twist=node_twist, num_lumped_mass=0) # Boundary conditions blade.StructuralInformation.boundary_conditions = np.zeros( (blade.StructuralInformation.num_node), dtype=int) blade.StructuralInformation.boundary_conditions[0] = 1 blade.StructuralInformation.boundary_conditions[-1] = -1 ###################################################################### ### AERODYNAMICS ###################################################################### # Read blade aerodynamic information from excel file rR_aero = gc.read_column_sheet_type01(excel_file_name, excel_sheet_aero_blade, 'rR') chord_aero = gc.read_column_sheet_type01(excel_file_name, excel_sheet_aero_blade, 'BlChord') thickness_aero = gc.read_column_sheet_type01(excel_file_name, excel_sheet_aero_blade, 'BlThickness') pure_airfoils_names = gc.read_column_sheet_type01( excel_file_name, excel_sheet_airfoil_info, 'Name') pure_airfoils_thickness = gc.read_column_sheet_type01( excel_file_name, excel_sheet_airfoil_info, 'Thickness') node_ElAxisAftLEc = np.interp(node_r, rR_structural * TipRad, ElAxisAftLEc) # Read coordinates of the pure airfoils n_pure_airfoils = len(pure_airfoils_names) pure_airfoils_camber = np.zeros((n_pure_airfoils, n_points_camber, 2), ) xls = pd.ExcelFile(excel_file_name) excel_db = pd.read_excel(xls, sheet_name=excel_sheet_airfoil_coord) for iairfoil in range(n_pure_airfoils): # Look for the NaN icoord = 2 while (not (math.isnan( excel_db["%s_x" % pure_airfoils_names[iairfoil]][icoord]))): icoord += 1 if (icoord == len(excel_db["%s_x" % pure_airfoils_names[iairfoil]])): break # Compute the camber of the airfoils at the defined chord points pure_airfoils_camber[iairfoil, :, 0], pure_airfoils_camber[ iairfoil, :, 1] = gc.get_airfoil_camber( excel_db["%s_x" % pure_airfoils_names[iairfoil]][2:icoord], excel_db["%s_y" % pure_airfoils_names[iairfoil]][2:icoord], n_points_camber) # Basic variables surface_distribution = np.zeros((blade.StructuralInformation.num_elem), dtype=int) # Interpolate in the correct positions node_chord = np.interp(node_r, rR_aero * TipRad, chord_aero) # Define the nodes with aerodynamic properties # Look for the first element that is goint to be aerodynamic first_aero_elem = 0 while (elem_r[first_aero_elem] <= rR_aero[0] * TipRad): first_aero_elem += 1 first_aero_node = first_aero_elem * ( blade.StructuralInformation.num_node_elem - 1) aero_node = np.zeros((blade.StructuralInformation.num_node, ), dtype=bool) aero_node[first_aero_node:] = np.ones( (blade.StructuralInformation.num_node - first_aero_node, ), dtype=bool) # Define the airfoil at each stage # airfoils = blade.AerodynamicInformation.interpolate_airfoils_camber(pure_airfoils_camber,excel_aero_r, node_r, n_points_camber) node_thickness = np.interp(node_r, rR_aero * TipRad, thickness_aero) airfoils = blade.AerodynamicInformation.interpolate_airfoils_camber_thickness( pure_airfoils_camber, pure_airfoils_thickness, node_thickness, n_points_camber) airfoil_distribution = np.linspace(0, blade.StructuralInformation.num_node - 1, blade.StructuralInformation.num_node, dtype=int) # User defined m distribution if (m_distribution == 'user_defined') and (user_defined_m_distribution_type == 'last_geometric'): blade_nodes = blade.StructuralInformation.num_node udmd_by_nodes = np.zeros((blade_nodes, chord_panels[0] + 1)) for inode in range(blade_nodes): r = np.linalg.norm( blade.StructuralInformation.coordinates[inode, :]) vrel = np.sqrt(rotation_velocity**2 * r**2 + wsp**2) last_length = vrel * dt / node_chord[inode] last_length = np.minimum(last_length, 0.5) if last_length <= 0.5: ratio = gc.get_factor_geometric_progression( last_length, 1., chord_panels) udmd_by_nodes[inode, -1] = 1. udmd_by_nodes[inode, 0] = 0. for im in range(chord_panels[0] - 1, 0, -1): udmd_by_nodes[inode, im] = udmd_by_nodes[inode, im + 1] - last_length last_length *= ratio # Check if (np.diff(udmd_by_nodes[inode, :]) < 0.).any(): sys.error( "ERROR in the panel discretization of the blade in node %d" % (inode)) else: print("ERROR: cannot match the last panel size for node:", inode) udmd_by_nodes[inode, :] = np.linspace(0, 1, chord_panels + 1) else: udmd_by_nodes = None node_twist = np.zeros_like(node_chord) if camber_effect_on_twist: print( "WARNING: The steady applied Mx should be manually multiplied by the density" ) for inode in range(blade.StructuralInformation.num_node): node_twist[inode] = gc.get_aoacl0_from_camber( airfoils[inode, :, 0], airfoils[inode, :, 1]) mu0 = gc.get_mu0_from_camber(airfoils[inode, :, 0], airfoils[inode, :, 1]) r = np.linalg.norm( blade.StructuralInformation.coordinates[inode, :]) vrel = np.sqrt(rotation_velocity**2 * r**2 + wsp**2) if inode == 0: dr = 0.5 * np.linalg.norm( blade.StructuralInformation.coordinates[1, :] - blade.StructuralInformation.coordinates[0, :]) elif inode == len(blade.StructuralInformation.coordinates[:, 0]) - 1: dr = 0.5 * np.linalg.norm( blade.StructuralInformation.coordinates[-1, :] - blade.StructuralInformation.coordinates[-2, :]) else: dr = 0.5 * np.linalg.norm( blade.StructuralInformation.coordinates[inode + 1, :] - blade.StructuralInformation.coordinates[inode - 1, :]) moment_factor = 0.5 * vrel**2 * node_chord[inode]**2 * dr # print("node", inode, "mu0", mu0, "CMc/4", 2.*mu0 + np.pi/2*node_twist[inode]) blade.StructuralInformation.app_forces[ inode, 3] = (2. * mu0 + np.pi / 2 * node_twist[inode]) * moment_factor airfoils[inode, :, 1] *= 0. # Write SHARPy format blade.AerodynamicInformation.create_aerodynamics_from_vec( blade.StructuralInformation, aero_node, node_chord, node_twist, np.pi * np.ones_like(node_chord), chord_panels, surface_distribution, m_distribution, node_ElAxisAftLEc, airfoil_distribution, airfoils, udmd_by_nodes) ###################################################################### ## ROTOR ###################################################################### # Read from excel file numberOfBlades = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'NumBl') tilt = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'ShftTilt') * deg2rad cone = gc.read_column_sheet_type01(excel_file_name, excel_sheet_parameters, 'Cone') * deg2rad # pitch = gc.read_column_sheet_type01(excel_file_name, excel_sheet_rotor, 'Pitch')*deg2rad # Apply pitch blade.StructuralInformation.rotate_around_origin(np.array([1., 0., 0.]), -pitch_deg * deg2rad) # Apply coning blade.StructuralInformation.rotate_around_origin(np.array([0., 1., 0.]), -cone) # Build the whole rotor rotor = blade.copy() for iblade in range(numberOfBlades - 1): blade2 = blade.copy() blade2.StructuralInformation.rotate_around_origin( np.array([0., 0., 1.]), (iblade + 1) * (360.0 / numberOfBlades) * deg2rad) rotor.assembly(blade2) blade2 = None rotor.remove_duplicated_points(tol_remove_points) # Apply tilt rotor.StructuralInformation.rotate_around_origin(np.array([0., 1., 0.]), tilt) return rotor
def __init__(self, tsaero0, tsstruct0): self.linear_system = None self.ss = None self.tsaero0 = tsaero0 self.tsstruct0 = tsstruct0 self.timestep_info = [] self.uvlm = None self.beam = None if __name__ == "__main__": print('Testing the assembly of the pendulum system') test = 'aeroelastic' if test == 'beam': data = h5.readh5( '/home/ng213/sharpy_cases/CC_DevTests/01_LinearAssembly/flexible_beam_static.data.h5' ).data beam_settings = { 'modal_projection': False, 'inout_coords': 'nodes', 'discrete_time': True, 'newmark_damp': 0.15 * 1, 'discr_method': 'newmark', 'dt': 0.001, 'proj_modes': 'undamped', 'use_euler': True, 'num_modes': 13, 'remove_dofs': ['V'], 'gravity': 'on' }
for ll in range(Nlin): PP = PPlist[ll] tplparams = (AlphaInfVecDeg[PP], AlphaVecDeg[PP], SideVecDeg[PP]) print(3 * '%.3f\t' % tplparams[:3]) Refs = [] for ll in range(Nlin): PP = PPlist[ll] tplparams = (int(np.round(100 * AlphaInfVecDeg[PP])), int(np.round(100 * AlphaVecDeg[PP])), int(np.round(100 * SideVecDeg[PP])), int(np.round(100 * RollVecDeg[PP]))) case_here = case_main + '_ainf%.4da%.4ds%.4dr%.4d' % tplparams route_here = route_main data0 = h5.readh5(route_here + case_here + '.data.h5').data Refs.append( extract_from_data(data0, assemble=True, zeta_pole=ZetaPole, build_Asteady_inv=True)) # ---------------------------------------------------------- loop through cases Dzeta_max = np.zeros((Nlin, Npoints)) # reference forces from exct analysis Fref = np.zeros((Npoints, 3)) Mref = np.zeros((Npoints, 3)) # linearised total forces
### update parameters os.system('mkdir -p %s'%(route_here,)) # Build wing model ws=flying_wings.Smith( M=M,N=N,Mstar_fact=Mstar_fact,n_surfaces=2, u_inf=u_inf,alpha=AlphaDeg, route=route_here, case_name=case_here) ws.clean_test_files() ws.update_derived_params() ws.generate_fem_file() ws.generate_aero_file() ws.set_default_config_dict() # update default configuration ws.config['SHARPy']['flow']=[ 'BeamLoader', 'AerogridLoader', 'StaticCoupled', 'SaveData'] ws.config['SaveData']={'folder': route_here, 'skip_attr': ['beam'], } ws.config.write() ### solve data=sharpy.sharpy_main.main(['path_to_solver_useless', route_here+case_here+'.solver.txt']) read=h5.readh5(route_here+case_here+'.data.h5')
fact = 1 if np.abs(freq_d) < 1e-3: fact = 1 / np.max(np.abs(v)) else: max_omega = max_angle * freq_d fact = np.max(np.abs(omega)) / max_omega return fact if __name__ == '__main__': u_inf = 140 try: data = h5.readh5( '/home/ng213/code/sharpy/tests/linear/goland_wing/cases/output/goland_u%04g.data.h5' % u_inf).data except FileNotFoundError: raise FileNotFoundError('Unable to find test case') integr_order = 2 predictor = True sparse = False aeroelastic_settings = { 'LinearUvlm': { 'dt': data.settings['LinearUvlm']['dt'], 'integr_order': integr_order, 'density': 1.020, 'remove_predictor': predictor, 'use_sparse': sparse,