ExamplesMeep Examples

Holey Waveguide Cavity

Analyze photonic crystal cavity modes formed by holes in a waveguide using Harminv

Holey Waveguide Cavity

This example simulates a photonic crystal cavity formed by introducing a defect in a periodic array of holes in a waveguide. The simulation finds resonant modes using Harminv analysis and computes transmission spectra.

Overview

Photonic crystal cavities are essential components for:

  • High-Q resonators for sensing and filtering
  • Cavity QED experiments
  • Laser cavities with enhanced light-matter interaction
  • Optical memories and slow-light devices

The holey waveguide cavity consists of a dielectric waveguide with a periodic array of air holes, where a defect (larger spacing) creates a localized cavity mode.

Simulation Parameters

ParameterDefault ValueDescription
resolution20Pixels per μm
eps13Dielectric constant of waveguide (Si)
w1.2Width of waveguide
r0.36Radius of air holes
d1.4Defect spacing (normal = 1)
N3Number of holes on each side
fcen0.25Pulse center frequency
df0.2Pulse frequency width

Physical Setup

The cavity structure:

  1. Waveguide: High-index dielectric slab (ε=13, like silicon)
  2. Holes: Periodic array of air holes (r=0.36)
  3. Defect: Central region with larger hole spacing (d=1.4)
  4. PML: Absorbing boundaries at cell edges

The defect spacing d > 1 creates a cavity mode by introducing a "potential well" in the photonic band gap.

Python Code

"""
Holey Waveguide Cavity with OptixLog Integration

Simulates transmission through a cavity formed by holes in a waveguide,
and finds resonant modes using Harminv analysis.

Based on the Meep tutorial: holey-wvg-cavity.py
Reference: S. Fan et al., J. Opt. Soc. Am. B, 12 (7), 1267-1272 (1995)
"""

import os
import argparse
import optixlog
import meep as mp
import matplotlib
matplotlib.use("agg")
import matplotlib.pyplot as plt
import numpy as np

api_key = os.getenv("OPTIX_API_KEY", "")
api_url = os.getenv("OPTIX_API_URL", "https://optixlog.com")
project_name = os.getenv("OPTIX_PROJECT", "MeepExamples")


def main(args):
    """Main simulation function for holey waveguide cavity."""
    
    if not optixlog.is_master_process():
        return
    
    try:
        run_type = "resonant_modes" if args.resonant_modes else "transmission"
        
        client = optixlog.init(
            api_key=api_key,
            api_url=api_url,
            project=project_name,
            run_name=f"holey_waveguide_cavity_{run_type}",
            config={
                "simulation_type": "cavity",
                "analysis_mode": run_type,
                "num_holes": args.N,
            },
            create_project_if_not_exists=True
        )
        
        # Simulation parameters
        resolution = 20
        eps = 13         # dielectric constant of waveguide
        w = 1.2          # width of waveguide
        r = 0.36         # radius of holes
        d = 1.4          # defect spacing
        N = args.N       # number of holes on either side
        
        sy = args.sy     # size of cell in y direction
        pad = 2          # padding between last hole and PML
        dpml = 1         # PML thickness
        
        sx = 2 * (pad + dpml + N) + d - 1
        
        fcen = args.fcen
        df = args.df
        
        # Log parameters
        client.log(
            step=0,
            resolution=resolution,
            waveguide_epsilon=eps,
            waveguide_width=w,
            hole_radius=r,
            defect_spacing=d,
            num_holes_per_side=N,
            center_frequency=fcen,
            frequency_width=df,
        )
        
        # Set up cell and geometry
        cell = mp.Vector3(sx, sy, 0)
        blk = mp.Block(size=mp.Vector3(mp.inf, w, mp.inf), material=mp.Medium(epsilon=eps))
        geometry = [blk]
        
        # Add holes
        for i in range(N):
            geometry.append(mp.Cylinder(r, center=mp.Vector3(d / 2 + i)))
            geometry.append(mp.Cylinder(r, center=mp.Vector3(-(d / 2 + i))))
        
        sim = mp.Simulation(
            cell_size=cell,
            geometry=geometry,
            sources=[],
            boundary_layers=[mp.PML(dpml)],
            resolution=resolution,
        )
        
        if args.resonant_modes:
            # Mode finding simulation
            sim.sources.append(
                mp.Source(
                    mp.GaussianSource(fcen, fwidth=df),
                    component=mp.Hz,
                    center=mp.Vector3()
                )
            )
            
            sim.symmetries.append(mp.Mirror(mp.Y, phase=-1))
            sim.symmetries.append(mp.Mirror(mp.X, phase=-1))
            
            harminv = mp.Harminv(mp.Hz, mp.Vector3(), fcen, df)
            
            sim.run(
                mp.at_beginning(mp.output_epsilon),
                mp.after_sources(harminv),
                until_after_sources=400,
            )
            
            modes = harminv.modes
            client.log(step=1, num_modes_found=len(modes))
            
            for i, mode in enumerate(modes):
                client.log(
                    step=2 + i,
                    mode_number=i + 1,
                    frequency=float(mode.freq),
                    quality_factor=float(mode.Q) if mode.Q > 0 else 0,
                )
                
        else:
            # Transmission spectrum simulation
            sim.sources.append(
                mp.Source(
                    mp.GaussianSource(fcen, fwidth=df),
                    component=mp.Ey,
                    center=mp.Vector3(-0.5 * sx + dpml),
                    size=mp.Vector3(0, w),
                )
            )
            
            sim.symmetries.append(mp.Mirror(mp.Y, phase=-1))
            
            freg = mp.FluxRegion(
                center=mp.Vector3(0.5 * sx - dpml - 0.5),
                size=mp.Vector3(0, 2 * w)
            )
            nfreq = 500
            trans = sim.add_flux(fcen, df, nfreq, freg)
            
            sim.run(
                mp.at_beginning(mp.output_epsilon),
                until_after_sources=mp.stop_when_fields_decayed(
                    50, mp.Ey, mp.Vector3(0.5 * sx - dpml - 0.5), 1e-3
                ),
            )
            
            flux_freqs = mp.get_flux_freqs(trans)
            flux_data = mp.get_fluxes(trans)
            
            client.log(
                step=2,
                num_frequencies=len(flux_freqs),
                max_transmission=float(np.max(flux_data)),
            )
        
    except Exception as e:
        print(f"Simulation Error: {e}")


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-r", "--resonant_modes", action="store_true", default=False)
    parser.add_argument("-N", type=int, default=3)
    parser.add_argument("-sy", type=int, default=6)
    parser.add_argument("-fcen", type=float, default=0.25)
    parser.add_argument("-df", type=float, default=0.2)
    args = parser.parse_args()
    main(args)

How to Run

# Set your OptixLog API key
export OPTIX_API_KEY="your_api_key_here"

# Find resonant modes with Harminv
python holey-wvg-cavity.py -r

# Compute transmission spectrum (default)
python holey-wvg-cavity.py

# Customize number of holes
python holey-wvg-cavity.py -N 5 -r

# Custom frequency range
python holey-wvg-cavity.py -fcen 0.3 -df 0.15

Results and Analysis

Resonant Mode Analysis

When running with -r flag, Harminv identifies the cavity's resonant modes:

  • Frequency: The resonant frequency in units of c/a
  • Quality Factor (Q): Measure of energy confinement (higher = better)
  • Decay Rate: Rate at which mode energy leaks from cavity

Typical results show a high-Q mode in the photonic band gap, with Q factors that increase with more holes (larger N).

Transmission Spectrum

The transmission spectrum shows:

  • Band gap: Frequency range with near-zero transmission
  • Cavity resonance: Sharp peak within the band gap
  • Band edges: Transition regions with high transmission

OptixLog Metrics

For resonant mode analysis:

  • num_modes_found: Total resonant modes detected
  • frequency: Mode frequency
  • quality_factor: Q factor for each mode

For transmission:

  • num_frequencies: Frequency points in spectrum
  • max_transmission: Peak transmission value

The Q factor scales exponentially with the number of holes N. Use N=3-5 for quick tests, N=10+ for high-Q applications.

Physical Insights

Quality Factor Scaling

The cavity Q factor depends on:

  • Number of holes N: Q ∝ exp(αN) for some constant α
  • Hole radius r: Affects band gap width
  • Defect spacing d: Tunes cavity frequency within band gap

Mode Profiles

The cavity supports modes with different symmetries:

  • Odd-y modes: Field antisymmetric about waveguide axis
  • Even-y modes: Field symmetric about waveguide axis

On this page