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)
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