Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
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()