Source code for cxroots.contours.Annulus

import numpy as np
from scipy import pi

from ..Contour import Contour
from ..Paths import ComplexLine, ComplexArc
from .AnnulusSector import AnnulusSector

[docs]class Annulus(Contour): """ An annulus in the complex plane with the outer circle positively oriented and the inner circle negatively oriented. Parameters ---------- center : complex The center of the annulus in the complex plane. radii : tuple A tuple of length two of the form (inner_radius, outer_radius). Examples -------- .. plot:: :include-source: from cxroots import Annulus annulus = Annulus(center=0, radii=(0.5,0.75)) annulus.show() """ def __init__(self, center, radii): self.center = center self.radii = radii self.axisName = ('r', 'phi') segments = [ComplexArc(center, radii[1], 0, 2*pi), ComplexArc(center, radii[0], 0, -2*pi)] super(Annulus, self).__init__(segments) def __str__(self): return 'Annulus: center={center.real:.3f}{center.imag:+.3f}i, inner radius={radii[0]:.3f}, outer radius={radii[1]:.3f}'.format(center=self.center, radii=self.radii) @property def centralPoint(self): # get the central point within the contour r = (self.radii[0] + self.radii[1])/2 return r @property def area(self): return pi*(self.radii[1]**2 - self.radii[0]**2) def contains(self, z): """ Returns True if the point z lies within the contour, False if otherwise """ return self.radii[0] < abs(z - self.center) < self.radii[1] def subdivide(self, axis, divisionFactor=0.5): """ Subdivide the contour Parameters ---------- axis : str, can be either 'r' or 'phi' The axis along which the line subdividing the contour is a constant. divisionFactor : float in range (0,1), optional Determines the point along 'axis' at which the line dividing the box is placed Returns ------- boxes : list of contours Two annuluses if axis is 'r'. Two half-annuluses oriented according to divisionFactor if axis is 'phi'. """ if axis == 'r' or self.axisName[axis] == 'r': midpoint = self.radii[0] + divisionFactor*(self.radii[1]-self.radii[0]) box1 = Annulus(self.center, [self.radii[0], midpoint]) box2 = Annulus(self.center, [midpoint, self.radii[1]]) box1.segments[1] = self.segments[1] box2.segments[0] = self.segments[0] box1.segments[0]._reversePath = box2.segments[1] box2.segments[1]._reversePath = box1.segments[0] box1._createdBySubdivisionAxis = axis box2._createdBySubdivisionAxis = axis elif axis == 'phi' or self.axisName[axis] == 'phi': # Subdividing into two radial boxes rather than one to # ensure that an error is raised if one of the new paths # is too close to a root # XXX: introduce another parameter for phi1 phi0 = 2*pi*divisionFactor phi1 = phi0 + pi box1 = AnnulusSector(self.center, self.radii, [phi0, phi1]) box2 = AnnulusSector(self.center, self.radii, [phi1, phi0]) box1.segments[0]._reversePath = box2.segments[2] box2.segments[2]._reversePath = box1.segments[0] box1.segments[2]._reversePath = box2.segments[0] box2.segments[0]._reversePath = box1.segments[2] for box in [box1, box2]: box._createdBySubdivisionAxis = axis box._parentBox = self self._childBoxes = [box1, box2] return box1, box2 def randomPoint(self): """ Returns a random point inside the Annulus """ r = np.random.uniform(*self.radii) phi = np.random.uniform(0,2*pi) return r*exp(1j*phi) + self.center