Esempio n. 1
0
    def plot_stability_region(self,N=100,N2=1000,color='r',filled=True, alpha=1.):
        r""" 
            The region of absolute stability of a linear multistep method is
            the set

            `\{ z \in C : \rho(\zeta) - z \sigma(zeta) \text{ satisfies the root condition} \}`

            where `\rho(zeta)` and `\sigma(zeta)` are the characteristic
            functions of the method.

            Also plots the boundary locus, which is
            given by the set of points z:

            `\{z | z=\rho(\exp(i\theta))/\sigma(\exp(i\theta)), 0\le \theta \le 2*\pi \}`

            Here `\rho` and `\sigma` are the characteristic polynomials 
            of the method.

            References:
                [leveque2007]_ section 7.6.1


            **Input**: (all optional)
                - N       -- Number of gridpoints to use in each direction
                - bounds  -- limits of plotting region
                - color   -- color to use for this plot
                - filled  -- if true, stability region is filled in (solid); otherwise it is outlined
        """
        import matplotlib.pyplot as plt
        from utils import find_plot_bounds
        numself = self.__num__()
        rho, sigma = self.__num__().characteristic_polynomials()
        mag = lambda z : _root_condition(rho-z*sigma)
        vmag = np.vectorize(mag)
        bounds = find_plot_bounds(vmag,guess=(-10,1,-5,5),N=101)

        y=np.linspace(bounds[2],bounds[3],N)
        Y=np.tile(y[:,np.newaxis],(1,N))
        x=np.linspace(bounds[0],bounds[1],N)
        X=np.tile(x,(N,1))
        Z=X+Y*1j

        R=1.5-vmag(Z)

        z = self._boundary_locus()

        if filled:
            plt.contourf(X,Y,R,[0,1],colors=color,alpha=alpha)
        else:
            plt.contour(X,Y,R,[0,1],colors=color,alpha=alpha)
        plt.title('Absolute Stability Region for '+self.name)
        plt.hold(True)
        plt.plot([0,0],[bounds[2],bounds[3]],'--k',linewidth=2)
        plt.plot([bounds[0],bounds[1]],[0,0],'--k',linewidth=2)
        plt.plot(np.real(z),np.imag(z),color='k',linewidth=3)
        plt.axis(bounds)
        plt.hold(False)
        plt.draw()
    def plot_stability_region(self,N=50,bounds=None,
                    color='r',filled=True,scaled=False):
        r""" 
            Plot the region of absolute stability
            of a Two-step Runge-Kutta method, i.e. the set

            `\{ z \in C : M(z) is power bounded \}`

            where $M(z)$ is the stability matrix of the method.

            **Input**: (all optional)
                - N       -- Number of gridpoints to use in each direction
                - bounds  -- limits of plotting region
                - color   -- color to use for this plot
                - filled  -- if true, stability region is filled in (solid); otherwise it is outlined
        """
        method = self.__num__() # Use floating-point coefficients for efficiency

        import matplotlib.pyplot as plt
        if bounds is None:
            from utils import find_plot_bounds
            stable = lambda z : max(abs(np.linalg.eigvals(method.stability_matrix(z))))<=1.0
            bounds = find_plot_bounds(np.vectorize(stable),guess=(-10,1,-5,5))
            if np.min(np.abs(np.array(bounds)))<1.e-14:
                print 'No stable region found; is this method zero-stable?'

        x=np.linspace(bounds[0],bounds[1],N)
        y=np.linspace(bounds[2],bounds[3],N)
        X=np.tile(x,(N,1))
        Y=np.tile(y[:,np.newaxis],(1,N))
        Z=X+Y*1j

        maxroot = lambda z : max(abs(np.linalg.eigvals(method.stability_matrix(z))))
        Mroot = np.vectorize(maxroot)
        R = Mroot(Z)

        if filled:
            plt.contourf(X,Y,R,[0,1],colors=color)
        else:
            plt.contour(X,Y,R,[0,1],colors=color)
        plt.title('Absolute Stability Region for '+self.name)
        plt.hold(True)
        plt.plot([0,0],[bounds[2],bounds[3]],'--k',linewidth=2)
        plt.plot([bounds[0],bounds[1]],[0,0],'--k',linewidth=2)
        plt.axis('Image')
        plt.hold(False)
Esempio n. 3
0
def plot_stability_region(p,q,N=200,color='r',filled=True,bounds=None,
                          plotroots=False,alpha=1.,scalefac=1.,fignum=None):
    r""" 
        Plot the region of absolute stability of a rational function; i.e. the set

        `\{ z \in C : |\phi (z)|\le 1 \}`

        Unless specified explicitly, the plot bounds are determined automatically, attempting to
        include the entire region.  A check is performed beforehand for
        methods with unbounded stability regions.
        Note that this function is not responsible for actually drawing the 
        figure to the screen (or saving it to file).

        **Inputs**: 
            - p, q  -- Numerator and denominator of the stability function 
            - N       -- Number of gridpoints to use in each direction
            - color   -- color to use for this plot
            - filled  -- if true, stability region is filled in (solid); otherwise it is outlined
            - plotroots -- if True, plot the roots and poles of the function
            - alpha -- transparency of contour plot
            - scalefac -- factor by which to scale region (often used to normalize for stage number)
            - fignum -- number of existing figure to use for plot

    """
    import matplotlib.pyplot as plt

    # Convert coefficients to floats for speed
    if p.coeffs.dtype=='object':
        p = np.poly1d([float(c) for c in p.coeffs])
    if q.coeffs.dtype=='object':
        q = np.poly1d([float(c) for c in q.coeffs])

    if bounds is None:
        from utils import find_plot_bounds
        # Check if the stability region is bounded or not
        m,n = p.order,q.order
        if (m < n) or ((m == n) and (abs(p[m])<abs(q[n]))):
            print 'The stability region is unbounded'
            bounds = (-10*m,m,-5*m,5*m)
        else:
            stable = lambda z : np.abs(p(z)/q(z))<=1.0
            bounds = find_plot_bounds(stable,guess=(-10,1,-5,5))
            if np.min(np.abs(np.array(bounds)))<1.e-14:
                print 'No stable region found; is this method zero-stable?'

        if (m == n) and (abs(p[m])==abs(q[n])):
            print 'The stability region may be unbounded'

    # Evaluate the stability function over a grid
    x=np.linspace(bounds[0],bounds[1],N)
    y=np.linspace(bounds[2],bounds[3],N)
    X=np.tile(x,(N,1))
    Y=np.tile(y[:,np.newaxis],(1,N))
    Z=X+Y*1j
    R=np.abs(p(Z*scalefac)/q(Z*scalefac))

    # Plot
    h = plt.figure(fignum)
    plt.hold(True)
    if filled:
        plt.contourf(X,Y,R,[0,1],colors=color,alpha=alpha)
    else:
        plt.contour(X,Y,R,[0,1],colors=color,alpha=alpha,linewidths=3)
    if plotroots: plt.plot(np.real(p.r),np.imag(p.r),'ok')
    if len(q)>1: plt.plot(np.real(q.r),np.imag(q.r),'xk')
    plt.plot([0,0],[bounds[2],bounds[3]],'--k',linewidth=2)
    plt.plot([bounds[0],bounds[1]],[0,0],'--k',linewidth=2)
    plt.axis('Image')
    plt.hold(False)
    return h
Esempio n. 4
0
def plot_stability_region(p,
                          q,
                          N=200,
                          color='r',
                          filled=True,
                          bounds=None,
                          plotroots=False,
                          alpha=1.,
                          scalefac=1.,
                          fignum=None):
    r""" 
        Plot the region of absolute stability of a rational function; i.e. the set

        `\{ z \in C : |\phi (z)|\le 1 \}`

        Unless specified explicitly, the plot bounds are determined automatically, attempting to
        include the entire region.  A check is performed beforehand for
        methods with unbounded stability regions.
        Note that this function is not responsible for actually drawing the 
        figure to the screen (or saving it to file).

        **Inputs**: 
            - p, q  -- Numerator and denominator of the stability function 
            - N       -- Number of gridpoints to use in each direction
            - color   -- color to use for this plot
            - filled  -- if true, stability region is filled in (solid); otherwise it is outlined
            - plotroots -- if True, plot the roots and poles of the function
            - alpha -- transparency of contour plot
            - scalefac -- factor by which to scale region (often used to normalize for stage number)
            - fignum -- number of existing figure to use for plot

    """
    import matplotlib.pyplot as plt

    # Convert coefficients to floats for speed
    if p.coeffs.dtype == 'object':
        p = np.poly1d([float(c) for c in p.coeffs])
    if q.coeffs.dtype == 'object':
        q = np.poly1d([float(c) for c in q.coeffs])

    if bounds is None:
        from utils import find_plot_bounds
        # Check if the stability region is bounded or not
        m, n = p.order, q.order
        if (m < n) or ((m == n) and (abs(p[m]) < abs(q[n]))):
            print 'The stability region is unbounded'
            bounds = (-10 * m, m, -5 * m, 5 * m)
        else:
            stable = lambda z: np.abs(p(z) / q(z)) <= 1.0
            bounds = find_plot_bounds(stable, guess=(-10, 1, -5, 5))
            if np.min(np.abs(np.array(bounds))) < 1.e-14:
                print 'No stable region found; is this method zero-stable?'

        if (m == n) and (abs(p[m]) == abs(q[n])):
            print 'The stability region may be unbounded'

    # Evaluate the stability function over a grid
    x = np.linspace(bounds[0], bounds[1], N)
    y = np.linspace(bounds[2], bounds[3], N)
    X = np.tile(x, (N, 1))
    Y = np.tile(y[:, np.newaxis], (1, N))
    Z = X + Y * 1j
    R = np.abs(p(Z * scalefac) / q(Z * scalefac))

    # Plot
    h = plt.figure(fignum)
    plt.hold(True)
    if filled:
        plt.contourf(X, Y, R, [0, 1], colors=color, alpha=alpha)
    else:
        plt.contour(X, Y, R, [0, 1], colors=color, alpha=alpha, linewidths=3)
    if plotroots: plt.plot(np.real(p.r), np.imag(p.r), 'ok')
    if len(q) > 1: plt.plot(np.real(q.r), np.imag(q.r), 'xk')
    plt.plot([0, 0], [bounds[2], bounds[3]], '--k', linewidth=2)
    plt.plot([bounds[0], bounds[1]], [0, 0], '--k', linewidth=2)
    plt.axis('Image')
    plt.hold(False)
    return h