Domains¶
Domains define the region of the complex plane where you want to visualize a function. Complexplorer provides several built-in domain types and supports custom domains through composition.
Built-in Domain Types¶
Rectangle¶
The most common domain type, representing a rectangular region in the complex plane.
import complexplorer as cp
# Square domain centered at origin
domain = cp.Rectangle(re_length=4, im_length=4, center=0+0j)
# Rectangular domain (non-square)
domain = cp.Rectangle(re_length=6, im_length=4, center=0+0j)
# Off-center domain
domain = cp.Rectangle(re_length=4, im_length=4, center=2+1j)
# Convenience: automatically square if only one length given
domain = cp.Rectangle(4, 4) # Square domain
Parameters:
re_length: Width (real axis extent)im_length: Height (imaginary axis extent)center: Complex number for domain center (default: 0+0j)square: If True, forces im_length = re_length (default: True when im_length not specified)
Use cases:
- General purpose visualization
- Functions with rectangular symmetry
- Exploring specific regions of the complex plane
Disk¶
A circular region centered at a point.
# Unit disk
domain = cp.Disk(radius=1, center=0)
# Larger disk
domain = cp.Disk(radius=3, center=0)
# Off-center disk
domain = cp.Disk(radius=2, center=1+1j)
Parameters:
radius: Disk radius (positive float)center: Complex number for disk center (default: 0+0j)
Use cases:
- Functions with rotational symmetry
- Bounded visualizations (avoids infinity for many functions)
- Unit disk is natural for Mobius transformations and conformal maps
Annulus¶
A ring-shaped region between two circles.
# Simple annulus
domain = cp.Annulus(inner_radius=0.5, outer_radius=2, center=0)
# Thin ring
domain = cp.Annulus(inner_radius=0.9, outer_radius=1.1, center=0)
# Off-center annulus
domain = cp.Annulus(inner_radius=1, outer_radius=3, center=2j)
Parameters:
inner_radius: Inner circle radius (positive float)outer_radius: Outer circle radius (must be > inner_radius)center: Complex number for annulus center (default: 0+0j)
Use cases:
- Functions with poles at origin (exclude singularity)
- Laurent series visualization
- Focusing on specific magnitude ranges
- Avoiding branch cuts
Domain Properties¶
All domains provide:
contains(z): Check if point(s) z are in the domainsample(resolution): Generate grid of points for visualization
domain = cp.Disk(radius=2, center=0)
# Check if point is in domain
point = 1 + 1j
if domain.contains(point):
print("Point is in domain")
# Check multiple points
points = np.array([0+0j, 1+1j, 3+3j])
mask = domain.contains(points) # Returns boolean array
Choosing the Right Domain¶
Different functions benefit from different domains:
Polynomial Functions¶
For polynomials like z^n, use a Disk or Rectangle:
Rational Functions¶
For rational functions with poles, use an Annulus to exclude singularities:
# Function has pole at origin
f = lambda z: 1/z
domain = cp.Annulus(inner_radius=0.2, outer_radius=3)
cp.plot(domain, f)
Functions with Branch Cuts¶
For functions like sqrt(z) or log(z), carefully position the domain to avoid branch cuts:
# sqrt(z) has branch cut on negative real axis
f = lambda z: np.sqrt(z)
# Position domain to avoid branch cut
domain = cp.Rectangle(4, 4, center=1+0j) # Centered at z=1 (positive real)
cp.plot(domain, f)
Mobius Transformations¶
For Mobius transformations, the unit disk is natural:
# Maps unit disk to itself (if |a| < 1)
a = 0.5 + 0.3j
f = lambda z: (z - a) / (1 - np.conj(a) * z)
domain = cp.Disk(radius=1)
cp.plot(domain, f)
Advanced: Domain Composition¶
Coming Soon
Domain composition through set operations (union, intersection, difference) is planned for a future release.
Domain Best Practices¶
1. Start with Default Domains¶
For exploration, use simple domains:
# Quick exploration with show()
cp.show(lambda z: z**2) # Uses Rectangle(-2, 2) x (-2i, 2i)
# Explicit default
domain = cp.Rectangle(4, 4)
2. Match Domain to Function Behavior¶
Consider where your function has:
- Poles: Exclude with Annulus
- Branch cuts: Position Rectangle carefully
- Rotational symmetry: Use Disk
- Rectangular symmetry: Use Rectangle
3. Avoid Infinity at Domain Boundary¶
For functions that blow up at infinity, use bounded domains:
# Bad: Rectangle can extend to large values
domain = cp.Rectangle(100, 100) # Function may be unstable at edges
# Good: Disk naturally bounds the domain
domain = cp.Disk(radius=5) # More stable visualization
4. Resolution Considerations¶
Larger domains need higher resolution for the same detail:
# Small domain - 400 points is plenty
domain = cp.Rectangle(2, 2)
cp.plot(domain, f, resolution=400)
# Large domain - need more points
domain = cp.Rectangle(10, 10)
cp.plot(domain, f, resolution=800)
5. Domain for STL Export¶
For 3D printing, carefully choose domains to avoid numerical issues:
from complexplorer.export.stl import OrnamentGenerator
# Exclude singularities with annulus
f = lambda z: 1 / (z**2 + 1)
domain = cp.Annulus(inner_radius=0.1, outer_radius=3)
ornament = OrnamentGenerator(func=f, domain=domain, resolution=150)
ornament.generate_and_save('ornament.stl', size_mm=80)
Domain Visualization Tips¶
Comparing Domain and Codomain¶
Use pair_plot() to see both input and output:
f = lambda z: z**2
domain = cp.Disk(radius=2)
# Shows domain on left, codomain on right
cp.pair_plot(domain, f, figsize=(12, 6))
Domain Shape in 3D¶
The domain shape is more apparent in 3D landscapes:
# Disk domain creates circular base
domain = cp.Disk(radius=2)
cp.plot_landscape_pv(domain, f)
# Annulus domain creates ring-shaped base
domain = cp.Annulus(0.5, 2)
cp.plot_landscape_pv(domain, f)
Examples by Function Type¶
Elementary Functions¶
# Exponential
f = lambda z: np.exp(z)
domain = cp.Rectangle(4, 4) # Unbounded, but centered view
# Sine/Cosine
f = lambda z: np.sin(z)
domain = cp.Rectangle(6, 6) # See multiple periods
# Power function
f = lambda z: z**n
domain = cp.Disk(radius=2) # Rotational symmetry
Rational Functions¶
# Simple pole
f = lambda z: 1/(z - 1)
domain = cp.Annulus(0.3, 3, center=1) # Exclude pole at z=1
# Multiple poles
f = lambda z: 1/(z**2 - 1)
domain = cp.Disk(radius=3) # Poles at +/-1, but domain includes them
# Better: exclude both poles
domain = cp.Rectangle(6, 6) # Rectangular domain shows both
Multi-valued Functions¶
# Square root (branch cut on negative real axis)
f = lambda z: np.sqrt(z)
domain = cp.Rectangle(4, 4, center=1+0j) # Avoid negative reals
# Logarithm (branch cut on negative real axis)
f = lambda z: np.log(z)
domain = cp.Disk(radius=3, center=1+0j) # Centered away from origin
Common Patterns¶
Exploring Function Near Origin¶
# Small disk for detailed view
domain = cp.Disk(radius=0.5)
cp.plot(domain, f, resolution=600) # High res for detail
Exploring Function at Infinity¶
# Large disk or use Riemann sphere
domain = cp.Disk(radius=10)
cp.plot(domain, f)
# Better: Riemann sphere shows infinity explicitly
cp.riemann_pv(f, modulus_mode='arctan')
Asymmetric Functions¶
# Function interesting in right half-plane
f = lambda z: np.exp(z) * np.sin(z)
domain = cp.Rectangle(4, 4, center=2+0j) # Centered at z=2
Next Steps¶
- Colormaps - Choose how to visualize your function
- 2D Plotting - Create 2D phase portraits
- 3D Plotting - Build 3D analytic landscapes
- Quick Start - Basic usage examples