def compute(self): self.ni = self.surface.shape[1] self.dom = Domain() self.dom.add_blocks(Block(self.surface[:, :, 0], self.surface[:, :, 1], self.surface[:, :, 2])) surforg = self.dom.blocks['block']._block2arr()[:, :, 0, :].copy() self.dom.rotate_z(self.struct_angle) x = np.interp(self.z, np.linspace(0, 1, self.ni), np.linspace(self.x[0], self.x[-1], self.ni)) y = np.interp(self.z, np.linspace(0, 1, self.ni), np.linspace(self.y[0], self.y[-1], self.ni)) self.pitch_axis = Curve(points=np.array([x, y, self.z]).T) self.pitch_axis.rotate_z(self.struct_angle) surf = self.dom.blocks['block']._block2arr()[:, :, 0, :].copy() self.afsorg = [] for i in range(surforg.shape[1]): self.afsorg.append(AirfoilShape(points=surforg[:, i, :])) self.afs = [] for i in range(surf.shape[1]): self.afs.append(AirfoilShape(points=surf[:, i, :])) if len(self.cap_DPs) == 0: raise RuntimeError('cap_DPs not specified') if len(self.le_DPs) == 0: raise RuntimeError('le_DPs not specified') if len(self.te_DPs) == 0: raise RuntimeError('te_DPs not specified') DPs = self.DPs # trailing edge DPs DPs[:, 0] = -1. DPs[:, -1] = 1. # extra TE regions DPs[:, 1] = -0.99 DPs[:, -2] = 0.99 for i in range(self.ni): af = self.afs[i] # Leading edge sLE = af.sLE lew = self.le_width[i] w0 = lew / 2. / af.smax s0 = sLE - w0 s1 = sLE + w0 s0 = -1.0 + s0 / sLE s1 = (s1-sLE) / (1.0-sLE) DPs[i, self.le_DPs[0]] = s0 DPs[i, self.le_DPs[1]] = s1 # lower trailing panel TEp = self.te_width[i] DPs[i, self.te_DPs[0]] = -1. + TEp / (sLE * af.smax) # upper trailing panel DPs[i, self.te_DPs[1]] = 1. - TEp / ((1. - sLE) * af.smax) # cap DPs PAx = self.pitch_axis.points[:, 0] for i in range(self.ni): af = self.afs[i] x_ccL = PAx[i] + self.cap_center_ps[i] s_ccL = af.interp_x(x_ccL, 'lower') x_ccU = PAx[i] + self.cap_center_ss[i] s_ccU = af.interp_x(x_ccU, 'upper') cwU = self.cap_width_ss[i] / 2 / af.smax cwL = self.cap_width_ps[i] / 2 / af.smax DPs[i, self.cap_DPs[0]] = af.s_to_11(s_ccL - cwL) DPs[i, self.cap_DPs[1]] = af.s_to_11(s_ccL + cwL) DPs[i, self.cap_DPs[2]] = af.s_to_11(s_ccU - cwU) DPs[i, self.cap_DPs[3]] = af.s_to_11(s_ccU + cwU) # web DPs x_cc = PAx[i] s_ccL = af.interp_x(x_cc, 'lower') s_ccU = af.interp_x(x_cc, 'upper') for j, web_ix in enumerate(self.web_def[1:]): wacc = getattr(self, 'w%02dpos' % (j+1))[i] swL = af.interp_x(x_cc+wacc, 'lower') swU = af.interp_x(x_cc+wacc, 'upper') DPs[i, web_ix[0]] = af.s_to_11(swL) DPs[i, web_ix[1]] = af.s_to_11(swU) if self.consistency_check == True: self.check_consistency()
class ComputeDPsParam2(object): """ Computes the region DPs based on the lofted surface and below listed parameters parameters ---------- surface: array lofted blade surface le_width: array total width of leading edge panel across leading edge as function of span te_width: array width of trailing edge panels on lower and upper surfaces as function of span cap_center_ss: array upper surface cap center position relative to reference axis as function of span cap_center_ps: array lower surface cap center position relative to reference axis as function of span cap_width_ss: array width of upper spar cap as function of span cap_width_ps: array width of lower spar cap as function of span w<%02d>pos: array Distance between web and cap center. Web attachment DPs are given in the st3d['web_def'] dict passed during init. te_DPs: list list of DP indices identifying the trailing edge reinforcement position. list should contain [lower_surface_DP, upper_surface_DP] le_DPs: list list of DP indices identifying the leading edge reinforcement position. list should contain [lower_surface_DP, upper_surface_DP] cap_DPs: list list of DPs identifying the edges of the spar caps. list should be numbered with increasing DP indices, i.e. starting at lower surface rear, ending at upper surface rear. returns ------- DPs: array Division points as function of span, size ((10, ni)) """ def __init__(self, st3d=None, **kwargs): """ Parameters ---------- st3d: dict blade structure definition (optional) kwargs: args init arguments to optionally set the class variables """ self.x = np.array([]) self.y = np.array([]) self.z = np.array([]) self.surface = np.array([]) try: self.web_def = st3d['web_def'] self.DPs = st3d['DPs'] self.s = st3d['s'] self.te_DPs = st3d['te_DPs'] self.le_DPs = st3d['le_DPs'] self.cap_DPs = st3d['cap_DPs'] self.dominant_regions = st3d['dominant_regions'] self.le_width = st3d['le_width'] self.te_width = st3d['te_width'] self.cap_width_ss = st3d['cap_width_ss'] self.cap_width_ps = st3d['cap_width_ps'] self.cap_center_ss = st3d['cap_center_ss'] self.cap_center_ps = st3d['cap_center_ps'] self.struct_angle = st3d['struct_angle'] for i, web_ix in enumerate(self.web_def[1:]): name = 'w%02dpos' % (i+1) setattr(self, name, st3d[name]) except: print 'failed reading st3d' self.web_def = [] self.DPs = np.array([]) self.s = np.array([]) self.te_DPs = [] self.le_DPs = [] self.cap_DPs = [] self.le_width = np.array([]) self.te_width = np.array([]) self.cap_width_ss = np.array([]) self.cap_width_ps = np.array([]) self.cap_center_ss = np.array([]) self.cap_center_ps = np.array([]) self.struct_angle = 0. self.dominant_regions = [] for i, web_ix in enumerate(self.web_def): setattr(self, 'w%02dpos' % i, np.array([])) self.consistency_check = True self.min_width = 0. for k, v in kwargs.iteritems(): if hasattr(self, k): setattr(self, k, v) else: print 'unknown key %s' % k def compute(self): self.ni = self.surface.shape[1] self.dom = Domain() self.dom.add_blocks(Block(self.surface[:, :, 0], self.surface[:, :, 1], self.surface[:, :, 2])) surforg = self.dom.blocks['block']._block2arr()[:, :, 0, :].copy() self.dom.rotate_z(self.struct_angle) x = np.interp(self.z, np.linspace(0, 1, self.ni), np.linspace(self.x[0], self.x[-1], self.ni)) y = np.interp(self.z, np.linspace(0, 1, self.ni), np.linspace(self.y[0], self.y[-1], self.ni)) self.pitch_axis = Curve(points=np.array([x, y, self.z]).T) self.pitch_axis.rotate_z(self.struct_angle) surf = self.dom.blocks['block']._block2arr()[:, :, 0, :].copy() self.afsorg = [] for i in range(surforg.shape[1]): self.afsorg.append(AirfoilShape(points=surforg[:, i, :])) self.afs = [] for i in range(surf.shape[1]): self.afs.append(AirfoilShape(points=surf[:, i, :])) if len(self.cap_DPs) == 0: raise RuntimeError('cap_DPs not specified') if len(self.le_DPs) == 0: raise RuntimeError('le_DPs not specified') if len(self.te_DPs) == 0: raise RuntimeError('te_DPs not specified') DPs = self.DPs # trailing edge DPs DPs[:, 0] = -1. DPs[:, -1] = 1. # extra TE regions DPs[:, 1] = -0.99 DPs[:, -2] = 0.99 for i in range(self.ni): af = self.afs[i] # Leading edge sLE = af.sLE lew = self.le_width[i] w0 = lew / 2. / af.smax s0 = sLE - w0 s1 = sLE + w0 s0 = -1.0 + s0 / sLE s1 = (s1-sLE) / (1.0-sLE) DPs[i, self.le_DPs[0]] = s0 DPs[i, self.le_DPs[1]] = s1 # lower trailing panel TEp = self.te_width[i] DPs[i, self.te_DPs[0]] = -1. + TEp / (sLE * af.smax) # upper trailing panel DPs[i, self.te_DPs[1]] = 1. - TEp / ((1. - sLE) * af.smax) # cap DPs PAx = self.pitch_axis.points[:, 0] for i in range(self.ni): af = self.afs[i] x_ccL = PAx[i] + self.cap_center_ps[i] s_ccL = af.interp_x(x_ccL, 'lower') x_ccU = PAx[i] + self.cap_center_ss[i] s_ccU = af.interp_x(x_ccU, 'upper') cwU = self.cap_width_ss[i] / 2 / af.smax cwL = self.cap_width_ps[i] / 2 / af.smax DPs[i, self.cap_DPs[0]] = af.s_to_11(s_ccL - cwL) DPs[i, self.cap_DPs[1]] = af.s_to_11(s_ccL + cwL) DPs[i, self.cap_DPs[2]] = af.s_to_11(s_ccU - cwU) DPs[i, self.cap_DPs[3]] = af.s_to_11(s_ccU + cwU) # web DPs x_cc = PAx[i] s_ccL = af.interp_x(x_cc, 'lower') s_ccU = af.interp_x(x_cc, 'upper') for j, web_ix in enumerate(self.web_def[1:]): wacc = getattr(self, 'w%02dpos' % (j+1))[i] swL = af.interp_x(x_cc+wacc, 'lower') swU = af.interp_x(x_cc+wacc, 'upper') DPs[i, web_ix[0]] = af.s_to_11(swL) DPs[i, web_ix[1]] = af.s_to_11(swU) if self.consistency_check == True: self.check_consistency() def check_consistency(self): """ check that there are no negative region widths and that DPs belonging to ps and ss are not on the wrong side of the LE. If negative widths are identified either of two things will be done: | 1) for all regular DPs the midpoint between the DPs is identified and the DPs are placed +/- 0.01% curve length to either side of this point. | 2) if one of the DPs is a dominant DP, the neighbour DP will be shifted by 0.02% curve length. """ DPs = self.DPs # check that ps and ss DPs are on the correct sides of the LE ps = range(self.te_DPs[0], self.le_DPs[0] + 1) ss = range(self.le_DPs[1], self.te_DPs[1] + 1) for i in range(self.ni): for j in ps: if self.afs[i].s_to_01(DPs[i, j]) > self.afs[i].sLE: DPs[i, j] = self.afs[i].s_to_11(self.afs[i].sLE) - self.min_width for j in ss: if self.afs[i].s_to_01(DPs[i, j]) < self.afs[i].sLE: DPs[i, j] = self.afs[i].s_to_11(self.afs[i].sLE) + self.min_width # check for negative region widths for i in range(self.ni): for j in range(1, DPs.shape[1]-1): if np.diff(DPs[i, [j, j+1]]) < 0.: if j-1 in self.dominant_regions and j+1 not in self.cap_DPs: DPs[i, j+1] = DPs[i, j] + self.min_width elif j+1 in self.dominant_regions and j not in self.cap_DPs: DPs[i, j] = DPs[i, j+1] - self.min_width else: mid = 0.5 * (DPs[i, j] + DPs[i, j+1]) DPs[i, j] = mid - self.min_width DPs[i, j+1] = mid + self.min_width def plot(self, isec=None, ifig=1, coordsys='rotor'): import matplotlib.pylab as plt if coordsys == 'rotor': afs = self.afsorg elif coordsys == 'mold': afs = self.afs plt.figure(ifig) if isec is not None: ni = [isec] else: ni = range(self.ni) for i in ni: plt.title('r = %3.3f' % (self.z[i])) af = afs[i] plt.plot(af.points[:, 0], af.points[:, 1], 'b-') DP = np.array([af.interp_s(af.s_to_01(s)) for s in self.DPs[i, :]]) width = np.diff(self.DPs[i, :]) valid = np.ones(DP.shape[0]) valid[1:] = width > self.min_width for d in DP: plt.plot(d[0], d[1], 'ro') for d in DP[self.cap_DPs, :]: plt.plot(d[0], d[1], 'mo') for web_ix in self.web_def: if valid[web_ix].all(): plt.plot(DP[[web_ix[0], web_ix[1]]][:, 0], DP[[web_ix[0], web_ix[1]]][:, 1], 'g') plt.axis('equal') def plot_topview(self, coordsys='rotor', ifig=None): import matplotlib.pylab as plt if coordsys == 'rotor': afs = self.afsorg elif coordsys == 'mold': afs = self.afs plt.figure(ifig) DPs = [] for i in range(self.ni): af = afs[i] plt.plot(af.points[:, 2], af.points[:, 0]) DP = [af.interp_s(af.s_to_01(s)) for s in self.DPs[i, :]] DPs.append(DP) for d in DP: plt.plot(d[2], d[0], 'ro') plt.show()