ExamplesMeep Examples

Bent Waveguide

Simulate electromagnetic field propagation through a 90-degree bent waveguide

Bent Waveguide

This example simulates electromagnetic field propagation through a 90-degree bent waveguide, demonstrating basic Meep simulation setup and field visualization.

Reference: This is one of the fundamental Meep tutorials demonstrating 2D waveguide simulations.


Physics Background

Waveguide Modes

A dielectric waveguide confines light through total internal reflection. The guided modes depend on:

  • Waveguide width
  • Refractive index contrast
  • Wavelength

Bend Loss

When a waveguide bends, some light radiates away from the guided mode, causing:

  • Radiation loss at the bend
  • Mode mismatch between straight and curved sections
  • Loss increases with tighter bends

Simulation Overview

Define Geometry

Create an L-shaped waveguide with high-epsilon material (ε=12) embedded in air.

Add Source

Place a continuous source at the waveguide input to excite the fundamental mode.

Run Simulation

Propagate fields through the waveguide until steady state.

Visualize Fields

Extract and plot field distributions and intensity patterns.


Configuration Parameters

ParameterValueDescription
resolution10Pixels per unit length
cell_size16×16Simulation cell dimensions
waveguide_epsilon12Relative permittivity (ε)
wavelength2√11 ≈ 6.63Source wavelength

Complete Code

"""
Bent Waveguide Analysis with OptixLog Integration

Simulates electromagnetic field propagation through a bent waveguide
with comprehensive field analysis and visualization.
"""

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


def main():
    api_key = os.getenv("OPTIX_API_KEY", "your_api_key_here")
    
    client = Optixlog(api_key=api_key)
    project = client.project(name="MeepExamples", create_if_not_exists=True)
    
    # Simulation parameters
    resolution = 10
    cell = mp.Vector3(16, 16, 0)
    wavelength = 2 * (11**0.5)  # Matches waveguide dispersion
    
    run = project.run(
        name="bent_waveguide_analysis",
        config={
            "simulation_type": "bent_waveguide",
            "resolution": resolution,
            "cell_size_x": cell.x,
            "cell_size_y": cell.y,
            "wavelength": wavelength,
            "waveguide_epsilon": 12
        }
    )
    
    run.log(step=0, resolution=resolution, wavelength=wavelength)

    # L-shaped waveguide geometry
    geometry = [
        # Horizontal arm
        mp.Block(
            mp.Vector3(12, 1, mp.inf),
            center=mp.Vector3(-2.5, -3.5),
            material=mp.Medium(epsilon=12),
        ),
        # Vertical arm
        mp.Block(
            mp.Vector3(1, 12, mp.inf),
            center=mp.Vector3(3.5, 2),
            material=mp.Medium(epsilon=12),
        ),
    ]
    
    pml_layers = [mp.PML(1.0)]
    
    sources = [
        mp.Source(
            mp.ContinuousSource(wavelength=wavelength, width=20),
            component=mp.Ez,
            center=mp.Vector3(-7, -3.5),
            size=mp.Vector3(0, 1),
        )
    ]
    
    sim = mp.Simulation(
        cell_size=cell,
        boundary_layers=pml_layers,
        geometry=geometry,
        sources=sources,
        resolution=resolution,
    )
    
    print("⚡ Running simulation...")
    sim.run(until=200)

    # Get field data
    eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric)
    ez_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Ez)
    intensity = np.abs(ez_data)**2

    # Create comprehensive plots
    fig, axes = plt.subplots(2, 2, figsize=(14, 12))
    
    # Permittivity distribution
    im1 = axes[0, 0].imshow(eps_data.T, interpolation='spline36', cmap='binary', origin='lower')
    axes[0, 0].set_title('Permittivity Distribution', fontsize=12)
    axes[0, 0].set_xlabel('X')
    axes[0, 0].set_ylabel('Y')
    plt.colorbar(im1, ax=axes[0, 0], label='ε')
    
    # Ez field (real part)
    im2 = axes[0, 1].imshow(np.real(ez_data).T, interpolation='spline36', cmap='RdBu', origin='lower')
    axes[0, 1].set_title('Ez Field (Real Part)', fontsize=12)
    axes[0, 1].set_xlabel('X')
    axes[0, 1].set_ylabel('Y')
    plt.colorbar(im2, ax=axes[0, 1], label='Ez')
    
    # Field intensity
    im3 = axes[1, 0].imshow(intensity.T, interpolation='spline36', cmap='hot', origin='lower')
    axes[1, 0].set_title('Field Intensity |Ez|²', fontsize=12)
    axes[1, 0].set_xlabel('X')
    axes[1, 0].set_ylabel('Y')
    plt.colorbar(im3, ax=axes[1, 0], label='Intensity')
    
    # Overlay: field on structure
    axes[1, 1].imshow(eps_data.T, interpolation='spline36', cmap='binary', alpha=0.3, origin='lower')
    im4 = axes[1, 1].imshow(intensity.T, interpolation='spline36', cmap='hot', alpha=0.7, origin='lower')
    axes[1, 1].set_title('Field in Waveguide Structure', fontsize=12)
    axes[1, 1].set_xlabel('X')
    axes[1, 1].set_ylabel('Y')
    plt.colorbar(im4, ax=axes[1, 1], label='Intensity')
    
    plt.tight_layout()
    run.log_matplotlib("bent_waveguide_analysis", fig)
    plt.close(fig)

    # Calculate metrics
    max_field = float(np.max(np.abs(ez_data)))
    max_intensity = float(np.max(intensity))
    total_power = float(np.sum(intensity))
    
    # Confinement ratio
    waveguide_mask = eps_data > 1.5
    confined_power = float(np.sum(intensity[waveguide_mask]))
    confinement_ratio = confined_power / total_power if total_power > 0 else 0

    run.log(step=2,
            max_field_amplitude=max_field,
            max_intensity=max_intensity,
            total_power=total_power,
            confinement_ratio=confinement_ratio,
            simulation_completed=True)
    
    print(f"📊 Confinement ratio: {confinement_ratio:.3f}")
    print(f"\n✅ Simulation complete!")


if __name__ == "__main__":
    main()

Key Concepts

Geometry Definition

Define waveguide structure using blocks:

geometry = [
    mp.Block(
        size=mp.Vector3(12, 1, mp.inf),  # width, height, depth
        center=mp.Vector3(-2.5, -3.5),
        material=mp.Medium(epsilon=12),
    ),
]

Continuous Source

For steady-state analysis, use a continuous source:

sources = [
    mp.Source(
        mp.ContinuousSource(wavelength=wavelength, width=20),
        component=mp.Ez,
        center=mp.Vector3(-7, -3.5),
        size=mp.Vector3(0, 1),  # Line source
    )
]

Field Extraction

Get field arrays after simulation:

eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric)
ez_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Ez)

Confinement Analysis

Calculate how much power stays in the waveguide:

waveguide_mask = eps_data > 1.5  # Identify waveguide region
confined_power = np.sum(intensity[waveguide_mask])
confinement_ratio = confined_power / total_power

Expected Results

Field Distribution

  • Light enters from the left horizontal arm
  • Propagates through the 90° bend
  • Some radiation loss at the corner
  • Continues in the vertical arm

Typical Confinement

For this waveguide design, expect ~60-80% confinement ratio depending on the bend geometry.


OptixLog Integration

Logged Metrics

MetricDescription
max_field_amplitudePeak Ez field value
max_intensityPeak
confinement_ratioPower in waveguide / total

Logged Plots

  • bent_waveguide_analysis — 4-panel visualization (permittivity, field, intensity, overlay)

Variations

Sharper Bend

Reduce the corner region for higher curvature (more loss).

Gradient Index Bend

Use graded permittivity at the corner to reduce radiation loss.

Multimode

Use wider waveguides or higher epsilon for multimode operation.


Further Reading

On this page