def cubic_interpolator(): b = BlendAirfoilShapes() b.airfoil_list = afs b.ni = 20 b.blend_var = [0.241, 0.301, 0.36] b.spline = 'cubic' b.initialize() return b
def cubic_interpolator(): b = BlendAirfoilShapes() b.airfoil_list = afs b.ni = 20 b.blend_var = [0.241, 0.301, 0.36] b.spline = "cubic" b.initialize() return b
def execute(self): self.interpolator = BlendAirfoilShapes() self.interpolator.ni = self.chord_ni self.interpolator.spline = self.surface_spline self.interpolator.blend_var = self.blend_var self.interpolator.airfoil_list = self.base_airfoils self.interpolator.initialize() self.span_ni = self.pf.s.shape[0] x = np.zeros((self.chord_ni, self.span_ni, 3)) for i in range(self.span_ni): s = self.pf.s[i] pos_x = self.pf.x[i] pos_y = self.pf.y[i] pos_z = self.pf.z[i] chord = self.pf.chord[i] p_le = self.pf.p_le[i] # generate the blended airfoil shape if self.interp_type == 'rthick': rthick = self.pf.rthick[i] points = self.interpolator(rthick) else: points = self.interpolator(s) points *= chord points[:, 0] += pos_x - chord * p_le # x-coordinate needs to be inverted for clockwise rotating blades x[:, i, :] = (np.array( [-points[:, 0], points[:, 1], x.shape[0] * [pos_z]]).T) # save non-rotated blade (only really applicable for straight blades) x_norm = x.copy() x[:, :, 1] += self.pf.y x = self.rotate(x) self.surfnorot.surface = x_norm self.surfout.surface = x
def execute(self): self.interpolator = BlendAirfoilShapes() self.interpolator.ni = self.chord_ni self.interpolator.spline = self.surface_spline self.interpolator.blend_var = self.blend_var self.interpolator.airfoil_list = self.base_airfoils self.interpolator.initialize() self.span_ni = self.pf.s.shape[0] x = np.zeros((self.chord_ni, self.span_ni, 3)) for i in range(self.span_ni): s = self.pf.s[i] pos_x = self.pf.x[i] pos_y = self.pf.y[i] pos_z = self.pf.z[i] chord = self.pf.chord[i] p_le = self.pf.p_le[i] # generate the blended airfoil shape if self.interp_type == "rthick": rthick = self.pf.rthick[i] points = self.interpolator(rthick) else: points = self.interpolator(s) points = self.redistribute(points, pos_z) points *= chord points[:, 0] -= chord * p_le # x-coordinate needs to be inverted for clockwise rotating blades x[:, i, :] = np.array([-points[:, 0], points[:, 1], x.shape[0] * [pos_z]]).T # save blade without sweep and prebend x_norm = x.copy() # add translation and rotation x[:, :, 0] += self.pf.x x[:, :, 1] += self.pf.y x = self.rotate(x) self.surfnorot.surface = x_norm self.surfout.surface = x
def execute(self): self.interpolator = BlendAirfoilShapes() self.interpolator.ni = self.chord_ni self.interpolator.spline = self.surface_spline self.interpolator.blend_var = self.blend_var self.interpolator.airfoil_list = self.base_airfoils self.interpolator.initialize() self.span_ni = self.pf.s.shape[0] x = np.zeros((self.chord_ni, self.span_ni, 3)) for i in range(self.span_ni): s = self.pf.s[i] pos_x = self.pf.x[i] pos_y = self.pf.y[i] pos_z = self.pf.z[i] chord = self.pf.chord[i] p_le = self.pf.p_le[i] # generate the blended airfoil shape if self.interp_type == 'rthick': rthick = self.pf.rthick[i] points = self.interpolator(rthick) else: points = self.interpolator(s) points *= chord points[:, 0] += pos_x - chord * p_le # x-coordinate needs to be inverted for clockwise rotating blades x[:, i, :] = (np.array([-points[:,0], points[:,1], x.shape[0] * [pos_z]]).T) # save non-rotated blade (only really applicable for straight blades) x_norm = x.copy() x[:, :, 1] += self.pf.y x = self.rotate(x) self.surfnorot.surface = x_norm self.surfout.surface = x
class LoftedBladeSurface(Component): pf = VarTree(BladePlanformVT(), iotype='in') base_airfoils = List(iotype='in') blend_var = Array(iotype='in') chord_ni = Int(300, iotype='in') span_ni = Int(300, iotype='in') interp_type = Enum('rthick', ('rthick', 's'), iotype='in') surface_spline = Str('akima', iotype='in', desc='Spline') rot_order = Array(np.array([2, 1, 0]), iotype='in', desc='rotation order of airfoil sections' 'default z,y,x (twist,sweep,dihedral)') surfout = VarTree(BladeSurfaceVT(), iotype='out') surfnorot = VarTree(BladeSurfaceVT(), iotype='out') def execute(self): self.interpolator = BlendAirfoilShapes() self.interpolator.ni = self.chord_ni self.interpolator.spline = self.surface_spline self.interpolator.blend_var = self.blend_var self.interpolator.airfoil_list = self.base_airfoils self.interpolator.initialize() self.span_ni = self.pf.s.shape[0] x = np.zeros((self.chord_ni, self.span_ni, 3)) for i in range(self.span_ni): s = self.pf.s[i] pos_x = self.pf.x[i] pos_y = self.pf.y[i] pos_z = self.pf.z[i] chord = self.pf.chord[i] p_le = self.pf.p_le[i] # generate the blended airfoil shape if self.interp_type == 'rthick': rthick = self.pf.rthick[i] points = self.interpolator(rthick) else: points = self.interpolator(s) points *= chord points[:, 0] += pos_x - chord * p_le # x-coordinate needs to be inverted for clockwise rotating blades x[:, i, :] = (np.array( [-points[:, 0], points[:, 1], x.shape[0] * [pos_z]]).T) # save non-rotated blade (only really applicable for straight blades) x_norm = x.copy() x[:, :, 1] += self.pf.y x = self.rotate(x) self.surfnorot.surface = x_norm self.surfout.surface = x def rotate(self, x): """ rotate blade sections accounting for twist and main axis orientation the blade will be built with a "sheared" layout, ie no rotation around y in the case of sweep. if the main axis includes a winglet, the blade sections will be rotated accordingly. ensure that an adequate point distribution is used in this case to avoid sections colliding in the winglet junction! """ main_axis = Curve(points=np.array([self.pf.x, self.pf.y, self.pf.z]).T) rot_normals = np.zeros((3, 3)) x_rot = np.zeros(x.shape) for i in range(x.shape[1]): points = x[:, i, :] rot_center = main_axis.points[i] # rotation angles read from file angles = np.array([ self.pf.rot_x[i], self.pf.rot_y[i], self.pf.rot_z[i] ]) * np.pi / 180. # compute rotation angles of main_axis t = main_axis.dp[i] rot = np.zeros(3) rot[0] = -np.arctan(t[1] / (t[2] + 1.e-20)) v = np.array([t[2], t[1]]) vt = np.dot(v, v)**0.5 rot[1] = (np.arcsin(t[0] / vt)) angles[0] += rot[0] angles[1] += rot[1] # compute x-y-z normal vectors of rotation n_y = np.cross(t, [1, 0, 0]) n_y = n_y / norm(n_y) rot_normals[0, :] = np.array([1, 0, 0]) rot_normals[1, :] = n_y rot_normals[2, :] = t # compute final rotation matrix rotation_matrix = np.matrix([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) for n, ii in enumerate(self.rot_order): mat = np.matrix(RotMat(rot_normals[ii], angles[ii])) rotation_matrix = mat * rotation_matrix # apply rotation x_rot[:, i, :] = dotXC(rotation_matrix, points, rot_center) return x_rot
class LoftedBladeSurface(Component): pf = VarTree(BladePlanformVT(), iotype="in") base_airfoils = List(iotype="in") blend_var = Array(iotype="in") chord_ni = Int(300, iotype="in") span_ni = Int(300, iotype="in") redistribute_flag = Bool(False, desc="redistribute points chordwise") x_chordwise = Array(iotype="in", desc="user specified chordwise distribution") interp_type = Enum("rthick", ("rthick", "s"), iotype="in") surface_spline = Str("akima", iotype="in", desc="Spline") rot_order = Array( np.array([2, 1, 0]), iotype="in", desc="rotation order of airfoil sections" "default z,y,x (twist,sweep,dihedral)", ) surfout = VarTree(BladeSurfaceVT(), iotype="out") surfnorot = VarTree(BladeSurfaceVT(), iotype="out") def execute(self): self.interpolator = BlendAirfoilShapes() self.interpolator.ni = self.chord_ni self.interpolator.spline = self.surface_spline self.interpolator.blend_var = self.blend_var self.interpolator.airfoil_list = self.base_airfoils self.interpolator.initialize() self.span_ni = self.pf.s.shape[0] x = np.zeros((self.chord_ni, self.span_ni, 3)) for i in range(self.span_ni): s = self.pf.s[i] pos_x = self.pf.x[i] pos_y = self.pf.y[i] pos_z = self.pf.z[i] chord = self.pf.chord[i] p_le = self.pf.p_le[i] # generate the blended airfoil shape if self.interp_type == "rthick": rthick = self.pf.rthick[i] points = self.interpolator(rthick) else: points = self.interpolator(s) points = self.redistribute(points, pos_z) points *= chord points[:, 0] -= chord * p_le # x-coordinate needs to be inverted for clockwise rotating blades x[:, i, :] = np.array([-points[:, 0], points[:, 1], x.shape[0] * [pos_z]]).T # save blade without sweep and prebend x_norm = x.copy() # add translation and rotation x[:, :, 0] += self.pf.x x[:, :, 1] += self.pf.y x = self.rotate(x) self.surfnorot.surface = x_norm self.surfout.surface = x def rotate(self, x): """ rotate blade sections accounting for twist and main axis orientation the blade will be built with a "sheared" layout, ie no rotation around y in the case of sweep. if the main axis includes a winglet, the blade sections will be rotated accordingly. ensure that an adequate point distribution is used in this case to avoid sections colliding in the winglet junction! """ main_axis = Curve(points=np.array([self.pf.x, self.pf.y, self.pf.z]).T) rot_normals = np.zeros((3, 3)) x_rot = np.zeros(x.shape) for i in range(x.shape[1]): points = x[:, i, :] rot_center = main_axis.points[i] # rotation angles read from file angles = np.array([self.pf.rot_x[i], self.pf.rot_y[i], self.pf.rot_z[i]]) * np.pi / 180.0 # compute rotation angles of main_axis t = main_axis.dp[i] rot = np.zeros(3) rot[0] = -np.arctan(t[1] / (t[2] + 1.0e-20)) v = np.array([t[2], t[1]]) vt = np.dot(v, v) ** 0.5 rot[1] = np.arcsin(t[0] / vt) angles[0] += rot[0] angles[1] += rot[1] # compute x-y-z normal vectors of rotation n_y = np.cross(t, [1, 0, 0]) n_y = n_y / norm(n_y) rot_normals[0, :] = np.array([1, 0, 0]) rot_normals[1, :] = n_y rot_normals[2, :] = t # compute final rotation matrix rotation_matrix = np.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) for n, ii in enumerate(self.rot_order): mat = np.matrix(RotMat(rot_normals[ii], angles[ii])) rotation_matrix = mat * rotation_matrix # apply rotation x_rot[:, i, :] = dotXC(rotation_matrix, points, rot_center) return x_rot def redistribute(self, points, pos_z): if self.redistribute_flag == False: return points airfoil = AirfoilShape(points=points) try: dist_LE = np.interp(pos_z, self.dist_LE[:, 0], self.dist_LE[:, 1]) except: dist_LE = None # pass airfoil to user defined routine to allow for additional configuration airfoil = self.set_airfoil(airfoil, pos_z) if self.x_chordwise.shape[0] > 0: airfoil = airfoil.redistribute_chordwise(self.x_chordwise) else: airfoil = airfoil.redistribute(ni=self.chord_ni, dLE=dist_LE) return airfoil.points def set_airfoil(self, airfoil, pos_z): if hasattr(self, "gf_height"): height = self.gf_height(pos_z) length_factor = self.gf_length_factor(pos_z) print "gf", pos_z, height, length_factor if height > 0.0: airfoil = airfoil.gurneyflap(height, length_factor) return airfoil def add_gurney_flap(self, s, gf_heights, gf_length_factor): """spline the gurney flap height and length factor curves""" self.gf_height = pchip(s, gf_heights) self.gf_length_factor = pchip(s, gf_length_factor)
class LoftedBladeSurface(Component): pf = VarTree(BladePlanformVT(), iotype='in') base_airfoils = List(iotype='in') blend_var = Array(iotype='in') chord_ni = Int(300, iotype='in') span_ni = Int(300, iotype='in') interp_type = Enum('rthick', ('rthick', 's'), iotype='in') surface_spline = Str('akima', iotype='in', desc='Spline') rot_order = Array(np.array([2,1,0]),iotype='in',desc='rotation order of airfoil sections' 'default z,y,x (twist,sweep,dihedral)') surfout = VarTree(BladeSurfaceVT(), iotype='out') surfnorot = VarTree(BladeSurfaceVT(), iotype='out') def execute(self): self.interpolator = BlendAirfoilShapes() self.interpolator.ni = self.chord_ni self.interpolator.spline = self.surface_spline self.interpolator.blend_var = self.blend_var self.interpolator.airfoil_list = self.base_airfoils self.interpolator.initialize() self.span_ni = self.pf.s.shape[0] x = np.zeros((self.chord_ni, self.span_ni, 3)) for i in range(self.span_ni): s = self.pf.s[i] pos_x = self.pf.x[i] pos_y = self.pf.y[i] pos_z = self.pf.z[i] chord = self.pf.chord[i] p_le = self.pf.p_le[i] # generate the blended airfoil shape if self.interp_type == 'rthick': rthick = self.pf.rthick[i] points = self.interpolator(rthick) else: points = self.interpolator(s) points *= chord points[:, 0] += pos_x - chord * p_le # x-coordinate needs to be inverted for clockwise rotating blades x[:, i, :] = (np.array([-points[:,0], points[:,1], x.shape[0] * [pos_z]]).T) # save non-rotated blade (only really applicable for straight blades) x_norm = x.copy() x[:, :, 1] += self.pf.y x = self.rotate(x) self.surfnorot.surface = x_norm self.surfout.surface = x def rotate(self, x): """ rotate blade sections accounting for twist and main axis orientation the blade will be built with a "sheared" layout, ie no rotation around y in the case of sweep. if the main axis includes a winglet, the blade sections will be rotated accordingly. ensure that an adequate point distribution is used in this case to avoid sections colliding in the winglet junction! """ main_axis = Curve(points=np.array([self.pf.x, self.pf.y, self.pf.z]).T) rot_normals = np.zeros((3,3)) x_rot = np.zeros(x.shape) for i in range(x.shape[1]): points = x[:, i, :] rot_center = main_axis.points[i] # rotation angles read from file angles = np.array([self.pf.rot_x[i], self.pf.rot_y[i], self.pf.rot_z[i]]) * np.pi / 180. # compute rotation angles of main_axis t = main_axis.dp[i] rot = np.zeros(3) rot[0] = -np.arctan(t[1]/(t[2]+1.e-20)) v = np.array([t[2], t[1]]) vt = np.dot(v, v)**0.5 rot[1] = (np.arcsin(t[0]/vt)) angles[0] += rot[0] angles[1] += rot[1] # compute x-y-z normal vectors of rotation n_y = np.cross(t, [1,0,0]) n_y = n_y/norm(n_y) rot_normals[0, :] = np.array([1,0,0]) rot_normals[1, :] = n_y rot_normals[2, :] = t # compute final rotation matrix rotation_matrix = np.matrix([[1.,0.,0.],[0.,1.,0.],[0.,0.,1.]]) for n, ii in enumerate(self.rot_order): mat = np.matrix(RotMat(rot_normals[ii], angles[ii])) rotation_matrix = mat * rotation_matrix # apply rotation x_rot[:, i, :] = dotXC(rotation_matrix, points, rot_center) return x_rot