Skip to content

About

Photonics for Rust: validated, fabrication-ready, and visible while it runs. Mode solvers, FDFD, FDTD, inverse design, layout and PDKs, with a live studio.

Topics

Resources

Contributing

Stars

8 stars

Watchers

0 watching

Forks

Repository files navigation

photonoxide: validated photonics for Rust

Crates.io PyPI Docs.rs CI MSRV License Validation Examples

Photonics for Rust: validated, and visible while it runs.

The photonoxide studio: a silicon strip's first mode travelling along it in 3D as the camera orbits; a ring resonator's transmission spectrum building up point by point, then the ring lit at resonance in 3D; a Mach-Zehnder interferometer wired on the chip and its spectrum appearing

The studio: a strip's mode travelling in 3D; a ring's spectrum by 2D FDFD building up live (sped up) and the ring lit at resonance; an MZI wired on the chip and simulated.

photonoxide is a photonics library for Rust and a desktop studio to use it with. It solves waveguide modes, FDFD and FDTD in 2D and 3D, and circuits of components, with adjoint gradients throughout. Every method is checked against an analytic solution or a published result, in a validation report that CI keeps current.

It is released milestone by milestone (changelog, roadmap); until 1.0 the API can change between milestones. The methods, examples and report are also at tachsin.gr/projects/photonoxide.

What it does

Getting started · API · Examples · What works in Rust, Python and MATLAB

The studio

photonoxide opens a window on a folder of jobs, runs and chips: the examples, each run in one click and checked against its paper; each component on its own page, its design in 3D, its models side by side, its runs, sweeps and corners; the Custom device for any other structure; runs played live or replayed (modes, fields, spectra, FDTD as the field propagates); the Academy's lessons with live charts; the materials catalogue; chips; the validation report; and the external solvers this machine has. The same program runs a job from the command line (photonoxide run job.yaml, --headless for batches). studio/README.md has every page and command.

A directional coupler's page: its gap widened and its coupled length changed with the sliders, the 3D view following each step, then its cross-section, drawn from above with the cut and across the two strips
Components: a directional coupler's gap and length moved, its 3D view following; then its cross-section.
The Materials page: lithium niobate's ordinary and extraordinary indices read off the plot, then AlGaAs's index as its aluminium fraction slider moves
Materials: LiNbO₃'s no and ne read off the plot; AlGaAs as its aluminium fraction moves.
The Validation page: two cases looked up and opened, showing what each computes and what it is checked against, with the math rendered
Validation: cases looked up and opened, each against its exact solution or paper.
The Academy: the ring resonator's lesson opened on its diagram, the ring and its bus drawn from above with R, w, g and the coupler's r and k, then turned in 3D; then its live chart, the radius and window set on a resonance at 1.55 µm, then the input coupling raised to a wide, shallow dip and lowered to critical coupling, where the through power reaches zero
Academy: the ring resonator's lesson opens on its device, drawn and in 3D; then its transmission follows the coupling as the slider moves, critical coupling at the dip's zero.

Install

Rust:

cargo add photonoxide

Pure Rust, with no C, Fortran or Python dependencies.

Python 3.10 or later, wheels for Linux, macOS and Windows, with uv:

uv add photonoxide          # in a uv project
uv pip install photonoxide  # or into the active environment

pip install photonoxide works too: the guide is docs/python.md, the API reference has every function. MATLAB uses the Python package: docs/python.md.

The studio: the photonoxide program for Linux (x86_64 and ARM64), Windows and macOS is on each release, and updates itself (downloads, channels).

A first example

220 nm of silicon in oxide at 1550 nm, each material with its published dispersion, and the slab's modes solved exactly. In Rust:

use photonoxide::material::{silica, silicon};
use photonoxide::mode::Polarization;
use photonoxide::mode::slab::Slab;
use photonoxide::units::{Length, Wavelength};

fn main() -> photonoxide::Result<()> {
    let wavelength = Wavelength::um(1.55)?;
    let si = silicon().refractive_index(wavelength)?.re; // Li 1980
    let oxide = silica().refractive_index(wavelength)?.re; // Malitson 1965
    let slab = Slab::new(oxide, si, oxide, Length::nm(220.0))?;
    for (name, polarization) in [("TE", Polarization::Te), ("TM", Polarization::Tm)] {
        for mode in slab.modes(polarization, wavelength) {
            println!("{name}{}: n_eff = {:.4}", mode.order(), mode.effective_index());
        }
    }
    Ok(())
}

In Python:

import photonoxide as phox

si = phox.refractive_index("si", wavelength_um=1.55).real    # Li 1980
ox = phox.refractive_index("sio2", wavelength_um=1.55).real  # Malitson 1965
for polarization in ("te", "tm"):
    for mode in phox.slab_modes(below=ox, core=si, above=ox, thickness_um=0.22,
                                polarization=polarization, wavelength_um=1.55):
        print(f"{polarization.upper()}{mode.order}: n_eff = {mode.effective_index:.4f}")

Both print TE0: n_eff = 2.8475 and TM0: n_eff = 2.0531. Each of the examples reproduces one paper's numbers and fails when it disagrees:

cargo run --release --example strip_waveguide   # or: just example strip_waveguide

Building from source

You need:

  • Rust, the latest stable through rustup (rustup update), 1.95 at least. Each Rust release brings its own LLVM, so a newer toolchain is also a newer code generator.
  • just for the commands below. It is optional: each recipe in the justfile is one plain command.
  • For the studio: Node.js and pnpm, and on Linux WebKitGTK and Tauri's other prerequisites (studio/README.md).
  • For the Python package: uv.
git clone https://github.com/tachsin/photonoxide
cd photonoxide
just build         # the library, in release mode
just test          # the unit tests
just studio        # the program as released, target/dist/photonoxide
just python-test   # the Python package in python/.venv, and its tests
just               # every recipe

The workspace has three optimized profiles:

Profile Settings Used for
release Cargo's defaults: opt-level = 3, LTO within each crate only, 16 codegen units CI, the tests and examples, a plain pnpm tauri build, the nightly builds
dist release, with lto = "thin" and codegen-units = 1 the released program and the Python wheels; just studio, just build-dist
fastest dist, with lto = "fat" just build-fastest

LTO across crates lets LLVM optimize photonoxide together with faer, which does its sparse LU, and one codegen unit lets it see each crate whole. Both make the build slower. For the fastest code on your own machine, also compile for its CPU:

just build-fastest
# without just:  RUSTFLAGS="-C target-cpu=native" cargo build --profile fastest
# in PowerShell: $env:RUSTFLAGS = "-C target-cpu=native"; cargo build --profile fastest

That build uses every instruction set the CPU has (AVX2, AVX-512, …), so it runs only on CPUs that have them.

Validation

Nothing is merged without an analytic test, a reproduction of a published result and a convergence test; adjoint gradients are checked against finite differences. Each case in the report states its source, tolerance and grid, and CI fails when a case fails or the committed report isn't the one the code writes. CI checks every example's output too.

Status

Milestone Scope Status
0.1 – 0.3 Units and materials, mode solvers, FDFD in 2D and 3D, the studio ✅ released
0.4 – 0.4.3 Components and circuits, compact models, a 3D preconditioner, multifrontal direct solves ✅ released
0.5 FDTD 2D and 3D, CPML, smoothing, sources, monitors, adjoints, a GPU kernel; solver backends loaded at run time ✅ released
0.5.1 Channels and backends Nightly built from main, MUMPS, SuperLU and Accelerate, the backend chosen from benchmarks, every mode in a region ✅ released
0.5.2 Many solves at once Ports as a block, recycling across sweeps, more contour-integral mode solvers, farming across processes ✅ released
0.5.3 QMR without the matrix QMR without its matrix where the matrix wouldn't fit, MUMPS 5.9 ✅ released
0.5.4 Geometry and devices Geometry for any device; the device library on pages of its own, with its models, runs, sweeps, corners and optimization; compact models; the chip built from devices; devices in Python and MATLAB ✅ released
0.5.5 Writing jobs and taking results away The job editor (the text beside the design, a popover of fields and expressions, a schema), YAML first, every example as a job too, exports of modes and fields in compressed files, GDS read into jobs planned
0.6 Thermal and electro-optic Heat, thermo-optic phase shifters, Pockels modulators, travelling-wave electrodes 🚧 next
0.6.1 Nonlinear integrated optics Transparency windows, phase matching, SHG, SFG, DFG, SPDC and FWM in waveguides, Kerr combs planned
0.6.2 Quantum light Linear-optical statistics, photon-pair sources, Gaussian states, loss budgets of quantum circuits planned
0.6.3 Eigenmode expansion and the mode solver's tools Eigenmode expansion, convergence to a tolerance, adaptive sweeps, effective area and fibre coupling, sidewall-roughness loss planned
0.7 Inverse design Topology and shape optimization with fabrication constraints planned
0.7.1 – 0.16 Distributed memory, carrier modulators, layout, RCWA and beam propagation, a device library, photonic crystals, plasmonics, nonlinear FDTD planned
1.0 A stable API planned

ROADMAP.md has the details, with what each item measured.

Principles

  • Validated: every number from a checked method, with its grid.
  • Pure Rust: libraries you install yourself are optional backends, loaded at run time and never required (the plan).
  • Reproducible: the same bits on any number of threads; every run replays.
  • Visible: the studio and the command line run the same job.

Contributing

Ideas, use cases and validation cases are as welcome as code: open an issue. CONTRIBUTING.md says what a pull request needs.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in photonoxide by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Photonics for Rust: validated, fabrication-ready, and visible while it runs. Mode solvers, FDFD, FDTD, inverse design, layout and PDKs, with a live studio.

Topics

Resources

Contributing

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages