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 nodepy.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)
    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 nodepy.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)
Exemple #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 nodepy.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')
            if m > 0:
                bounds = (-10*m,m,-5*m,5*m)
            else:
                bounds = (-10,1,-5,5)
        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)
    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')
    return h
Exemple #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 nodepy.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')
            if m > 0:
                bounds = (-10*m,m,-5*m,5*m)
            else:
                bounds = (-10,1,-5,5)
        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)
    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')
    return h