Skip to content

phys-sims/cpa-sim

Repository files navigation

cpa-sim

A modular chirped-pulse amplification (CPA) simulation package.

cpa-sim is a physics-oriented pipeline for modeling a canonical CPA chain: pulse initialization → stretcher → fiber propagation → amplification → compressor → metrics.

The project is structured to keep stage interfaces stable while allowing backend implementations to evolve (for example, from placeholder deterministic transforms to solver-backed physics models).

Why this project exists

CPA experiments and design studies need repeatable simulation workflows with:

  • consistent units and sign conventions,
  • deterministic runs (same config + seed → same summary outputs),
  • stage-level provenance and metric reporting,
  • test tiers that separate fast contract checks from slower physics regression checks.

cpa-sim focuses on those software guarantees first so model fidelity can scale safely over time.

Stage flow

The default v1 chain is shown below.

flowchart LR
    A["PulseInitStage<br/>Initialize pulse and grid"] --> B["FreeSpaceStage<br/>Stretcher"]
    B --> C["FiberStage<br/>Nonlinear propagation"]
    C --> D["AmpStage<br/>Gain model"]
    D --> E["FreeSpaceStage<br/>Compressor"]
    E --> F["MetricsStage<br/>Compute metrics and plots"]
    F --> G["ReportStage (optional)<br/>Summarize provenance and validation"]
Loading

Current implementation snapshot

The repository currently provides:

  • a deterministic sequential pipeline builder and runner,
  • typed configuration/state models,
  • stage registries/backends for laser generation, free-space, fiber, amplification, and metrics,
  • test markers for unit, integration, physics, and slow workflows.

See STATUS.md for progress tracking and release-readiness checklists.

Installation

Runtime install

pip install -e .

Development install

pip install -e .[dev]
# optional WUST-FOG backend dependency
pip install -e .[gnlse]

Quickstart (CLI first)

1) Install

pip install -e .

For development tooling and optional WUST-FOG gnlse backend support:

pip install -e .[dev]
pip install -e .[gnlse]

2) Run a canonical config from configs/examples/

cpa-sim run configs/examples/treacy_stage_validation.yaml --out out/treacy-stage-validation

Other canonical examples:

# optional: these require the WUST-FOG gnlse dependency
cpa-sim run configs/examples/simple_fiber_dispersion.yaml --out out/simple-fiber-dispersion
cpa-sim run configs/examples/wave_breaking_raman.yaml --out out/wave-breaking-raman
cpa-sim run configs/examples/fiber_amp_spm.yaml --out out/fiber-amp-spm
cpa-sim run configs/examples/end_to_end_1560nm.yaml --out out/end-to-end-1560nm

3) Inspect output artifacts

Each run writes these CLI artifacts into --out:

  • metrics.json (overall + per-stage metrics),
  • artifacts.json (artifact path registry),
  • stage_plots/ with per-stage SVG time-intensity and spectrum plots,
  • metrics-stage input/output overlays (metrics_time_intensity_overlay.svg, metrics_spectrum_overlay.svg),
  • optional state_final.npz when --dump-state-npz is passed.

Example with NPZ state dump enabled:

cpa-sim run configs/examples/treacy_stage_validation.yaml --out out/treacy-stage-validation --dump-state-npz

4) Reproducibility note (fixed seed)

Use a fixed runtime.seed in your YAML config to keep summary outputs deterministic for a given config + backend setup. The checked-in configs under configs/examples/ are intended as stable starting points for reproducible runs.

Quickstart (Python API, secondary)

from cpa_sim.models import PipelineConfig
from cpa_sim.pipeline import run_pipeline

cfg = PipelineConfig()  # start from deterministic defaults
result = run_pipeline(cfg)

print(result.metrics)
print(result.state.meta)

v1 support matrix

Stage type kind values available now Notes
laser_gen analytic Deterministic pulse/grid initialization backend.
free_space treacy_grating_pair, phase_only_dispersion Used for stretcher/compressor roles depending on stage placement.
fiber fiber Physics/numerics split with numerics.kind (toy_phase or wust_gnlse).
amp simple_gain, fiber_amp_wrap Simple gain and a fiber amplifier wrapper backend.
metrics standard Canonical metrics/artifact recording backend (always final stage in pipeline).

Related docs:

  • Examples: docs/examples/simple-fiber-dispersion.md, docs/examples/wave-breaking-raman.md, docs/examples/fiber-amp-spm.md, docs/examples/treacy-stage-validation.md, docs/examples/end-to-end-1560nm.md
  • Validation: docs/validation/auto_window.md
  • ADRs: docs/adr/ADR-0001-conventions-units.md, docs/adr/ADR-0002-result-schema-contract.md, docs/adr/ADR-0003-validation-tiers-ci-policy.md, docs/adr/ADR-0008-canonical-output-layout.md

AutoWindow (free-space wraparound guard)

Use AutoWindow policy flags from the CLI to auto-rerun eligible free-space stages with a larger time window when edge wraparound is detected:

cpa-sim run configs/examples/treacy_stage_validation.yaml --out out/treacy-stage-validation --auto-window --auto-window-print

With --auto-window and no --auto-window-stages, pipeline policy defaults target configured free-space stages only. Include fiber stage names explicitly in --auto-window-stages (or cpa.auto_window.stages in Python policy) when you want fiber auto-reruns.

See docs/validation/auto_window.md for limits (including why this does not fix Nyquist aliasing).

Configuration model (high-level)

The top-level PipelineConfig includes these sections:

  • runtime (seed and run controls),
  • laser_gen (initial pulse/beam specification),
  • stretcher / compressor defaults (free-space configs used when stages is not set),
  • fiber (FiberStageCfg with stable physics plus backend-specific numerics),
  • amp (amplifier backend config; supports simple_gain and fiber_amp_wrap with power_out_w control),
  • stages (optional arbitrary ordered list of free_space, fiber, and amp stage configs),
  • metrics (summary metric backend; always appended at pipeline end).

This keeps public configuration stable while backend selection happens per stage via kind.

Runtime config vs stage config vs pipeline policy

  • runtime is run-level metadata/control (for example seed) and is not a processing stage.
  • stage configs (laser_gen, stretcher, fiber, amp, compressor, metrics) define model parameters and backend kind per stage.
  • policy is a pipeline-wide override bag passed at execution time for cross-cutting controls (debug/tolerances/instrumentation) without changing stage config shape.

In short: runtime and policy are global execution concerns, while stage configs define the physical chain itself.

Configurable stage ordering

PipelineConfig.stages allows arbitrary permutations of free-space, fiber, and amp stages. When omitted, the legacy default order remains stretcher -> fiber -> amp -> compressor. laser_gen is always the first stage and metrics is always the final stage, so baseline runs without stretching/compression can be expressed by omitting free-space entries from stages.

Stage plot policy

CLI runs now emit per-stage time/spectrum SVG plots by default into <out>/stage_plots/. If you use the Python API directly, pass runtime policy {"cpa.emit_stage_plots": true} and optionally set "cpa.stage_plot_dir".

PulseSpec quickstart inputs (power/energy units)

For new configs, prefer average-power-driven inputs in lab units:

laser_gen:
  spec:
    pulse:
      shape: gaussian
      avg_power_w: 0.5     # average power [W]
      rep_rate_mhz: 80.0   # repetition rate [MHz]
      width_fs: 120.0      # pulse intensity FWHM [fs]
      center_wavelength_nm: 1030.0

avg_power_w is in watts and rep_rate_mhz is in MHz.

See docs/config/pulse_spec.md for full PulseSpec behavior, including autocorrelation input rules and legacy compatibility.

Prefer these user-facing pulse normalization fields:

  • peak_power_w (direct peak power),
  • avg_power_w + rep_rate_mhz (lab-friendly average power), or
  • pulse_energy_j (single-pulse energy workflows).

width_fs is the pulse intensity FWHM. If your source measurement is from an autocorrelator, provide intensity_autocorr_fwhm_fs with a supported shape (gaussian or sech2) and the simulator will deconvolve to intensity FWHM internally.

Internally, the envelope still uses sqrt(W) scaling where |E(t)|^2 is instantaneous power in W, and pulse energy is sum(|E|^2 * dt_fs * 1e-15) joules.

Legacy compatibility (deprecated): amplitude is still accepted but should be migrated to peak_power_w/avg_power_w/pulse_energy_j in new configs.

For fiber_amp_wrap, power_out_w is the target output average power in watts at the stage output plane.

Canonical examples

Runnable example logic lives in src/cpa_sim/examples/* and is invoked via module entrypoints.

python -m cpa_sim.examples.simple_fiber_dispersion
python -m cpa_sim.examples.wave_breaking_raman
python -m cpa_sim.examples.fiber_amp_spm
python -m cpa_sim.examples.treacy_stage_validation
python -m cpa_sim.examples.end_to_end_1560nm

See docs/examples/ for per-example guides.

Public measurement data

Small public measurement datasets live under data/public/. Unpublished lab data should stay under the gitignored data/local/ mirror layout.

The initial checked-in showcase dataset is data/public/edfa_spectra/. It includes:

  • raw Agilent/HP 86142B exports under raw/2026-03-05/,
  • deterministic parsed CSV and metadata JSON outputs under processed/2026-03-05/,
  • a stable manifest.csv for dataset discovery via dataset_id.

Examples, tests, and future tuning workflows should resolve measurement inputs through manifest.csv plus dataset_id; they should not reconstruct file paths from filenames or date folders.

Rebuild the checked-in processed outputs and manifest from the raw exports with:

python scripts/measurements/rebuild_public_edfa_spectra.py

Outputs and provenance

cpa-sim run ... --out <dir> uses this canonical output layout:

  • metrics.json (schema cpa.metrics.v1)
    • overall: aggregate flat metric map
    • per_stage: stage-grouped metric map
  • artifacts.json (schema cpa.artifacts.v1)
    • paths: artifact-name to file-path map
  • stage_plots/
    • <stage>_time_intensity.svg
    • <stage>_spectrum.svg
    • metrics_time_intensity_overlay.svg
    • metrics_spectrum_overlay.svg
  • state_final.npz (optional via --dump-state-npz)

A run returns a StageResult with deterministic state, metrics, and provenance metadata in state.meta.

Validation strategy

The test strategy follows tiered validation:

  • Unit tests for schema contracts and invariants,
  • Integration tests for end-to-end tiny-chain execution,
  • Physics tests for canonical/golden targets (tracked as roadmap work),
  • Slow tests for larger or longer-running scenarios.

Common local commands:

python -m ruff format .
python -m pre_commit run -a
# if hooks modify files, rerun pre-commit until it passes
python -m pre_commit run -a
python -m mypy src
python -m pytest -q -m "not slow and not physics" --durations=10

Documentation

This repository includes a MkDocs Material site built from docs/.

Run docs locally

pip install -e .[dev]
pip install -r docs/requirements.txt
mkdocs serve

Then open the local URL printed by MkDocs (typically http://127.0.0.1:8000).

CI workflow behavior

  • On pull requests, .github/workflows/docs-pr.yml builds the documentation with mkdocs build --strict and uploads site/ as a workflow artifact.
  • On manual trigger (workflow_dispatch) and nightly schedule, .github/workflows/docs-publish.yml builds and deploys to GitHub Pages using the official Pages actions.

GitHub Pages setup note

For manual deployment to work, enable GitHub Pages in repository settings with Build and deployment: GitHub Actions.

Repository layout

src/cpa_sim/
  measurements/      # parser and manifest-loader utilities for measurement datasets
  models/            # configuration, state, provenance models
  stages/            # stage interfaces + backend implementations
  pipeline.py        # chain assembly and deterministic execution entrypoint

data/
  public/            # small publishable measurement datasets tracked in Git
  local/             # unpublished lab data (gitignored)

tests/
  unit/              # fast contract/invariant tests
  integration/       # fast end-to-end smoke tests
  physics/           # canonical physics regression tests

Roadmap themes

Near-term focus areas include:

  1. maturing physics backends and canonical reference cases,
  2. expanding artifact/report generation,
  3. hardening schema/contract documentation,
  4. introducing a stable CLI workflow.

For concrete status, see STATUS.md and ADRs in docs/adr/.

Contributing

Before opening a PR, run required quality gates:

python -m ruff format .
python -m pre_commit run -a
# if hooks modify files, rerun pre-commit until it passes
python -m pre_commit run -a
python -m mypy src
python -m pytest -q -m "not slow and not physics" --durations=10

Keep docs and status files synchronized when behavior changes.

License

See LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages