Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CLI (`ultrafast`), a C API, a Python package (`ultrafast`) and plugins (fitting,
```bash
dotnet build UltrafastEngine.sln -c Release
dotnet run --project tests/UltrafastEngine.Tests -f net10.0 -c Release # C# tests (-- --slow: all; -- Name: filter)
./setup.sh --cli --python --venv .venv --check # first-time source build (docs/install.md; --plugins chooses plugins)
python3 python/tools/build_engine.py && python3 -m pytest python/tests # Python
python3 -m mkdocs build --strict # docs
./build.sh --help # release packages (docs/releasing.md)
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@

## Unreleased

**Added (install and build)**
- **`docs/install.md`**: one page with a "what do you want?" table (release install, source build, Python, C API, individual plugins), the hosted-versus-native Python engine, troubleshooting and a box of steps for AI agents. The README quick start, `getting-started.md`, `python/README.md` (its link to a missing `docs/python.md` is fixed), `releasing.md` and `llms.txt` point to it.
- **`build/setup.py`** (`./setup.sh`, `setup.bat`): source builds for this machine. `--cli`, `--python` (+ `--venv`, `--python-engine hosted|native`), `--cpp`, `--plugins A B` (only those and what their `plugin.json` requires), `--plugin-only A` (rebuild one plugin and refresh it in existing builds), `--check` (smoke test), `--doctor`, `--dry-run`, `--clean-native` (removes a stale NativeAOT library that shadows the hosted Python engine; never done unasked). `python/tools/build_engine.py` gains `--plugins` and `--framework` and is now importable; its output is unchanged without them.
- **`install.py --preset`** (`cli`, `cli-plugins`, `python`, `python-native`, `cpp`, `full`) as shorthand for `--include`, and a "Next:" summary after an install.
- Python tests `test_setup_and_calc.py` (plugin resolution, `setup.py --dry-run`, presets).

**Fixed (install)**
- **An engine library older than the Python package no longer breaks every call.** The loader bound all exports at load time, so a NativeAOT library built before `uf_pulse_calc` existed failed with `dlsym ... symbol not found` on the first engine call (`uf.version()`, `uf.run`), whatever the script did. Exports added since the first release are now optional (`_native.OPTIONAL`); calling a missing one raises an error that says to rebuild. Test `test_missing_optional_export_gives_a_clear_error_not_a_load_failure`.
- **`setup.py --check` tested the wrong engine:** it set `ULTRAFAST_LIBRARY` to the new hosted build, which hid a stale `bin/native` library that `import ultrafast` loads first. It now tests what a plain import loads, and `setup.py --python` exits with an error (not a warning) when a stale library shadows the build; `--clean-native` removes it.

**Added (pulse calculator)**
- **`ultrafast pulse shapes|limit|analyze|measure`**, `uf_pulse_calc` (C API) and `ultrafast.calc` (Python): time-bandwidth product of Gaussian (0.4413), sech² (0.3148) and rectangular (0.8859) pulses, transform-limited duration or bandwidth (Hz or m with a centre wavelength), the product, ratio to the limit and stretch factor of a pulse from its widths or from measured arrays (FWHM and rms products), and the GDD magnitude of a chirped Gaussian. Docs: `reference/pulse-calculator.md`. Tests: `PulseCalculatorTests` (5), `test_setup_and_calc.py`.

**Fixed (physics)**
- **Avalanche and inverse bremsstrahlung were counted twice** (solids, where the avalanche is on by default): the avalanche loss `aval U / (2 k0 I)` equals `sigma rho / (2 k0)`, the Drude imaginary part, so the field lost the energy twice. The avalanche now only generates electrons; the field loses the energy once (`Plasma_Avalanche_DoesNotAbsorbTheFieldASecondTime`: output energy 5.15e-10 J, was 2.67e-10 J). Results of solid-state plasma runs with the avalanche on change.
- **Keldysh rate returned NaN in the far wing of a pulse** (field so weak that the Keldysh parameter exceeds 1e6): returns 0.
- **net48:** `ultrafast reference materials` printed `56.306399999999996` for `56.3064` (.NET Framework's `"R"`), so the committed page differed on Mono; the shortest round-trip form is used on both.

**Added**
- **`sameAs` on every element** (identical elements): `{"id": "pass2", "sameAs": "pass1"}` is the same physical object as `pass1` (same type and numbers, so a fit of a transform moves all its passes), but compiles on its own with its own pulse, beam, record and loss booking. A copy may set only `label`, `enabled`, wiring and per-pass geometry (`aoiDeg`, `aoiRad`, `tiltXRad`, `side`, `output`). Replaces the beam-splitter-only `sameAs`; existing files keep working. Python `same_as`. A fit path into a copy is refused. Docs: `reference/system-file.md#identical-elements`.
- `physics.strictMaterialsAllow`: catalogue paths (`"CS2.n2"`) or entry names that strict mode accepts although they are not verified.
- The generic defaults (thermal data of a user-defined gain medium: 10 W/(m K), 7.8e-6 1/K; ionisation inputs of a solid without data) are catalogue entries (`defaults:gainMedium`, `defaults:solidIonization`, status `unverified`); a run that uses one lists it in its notes and `unverifiedInputs`.
- Partial ionisation overrides: the run notes name the fields the run gave and say the rest come from the catalogue.
Expand Down
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ dotnet build UltrafastEngine.sln -c Release # e
dotnet build tests/UltrafastEngine.Tests -c Release -f net10.0 # just the tests + what they need
dotnet tests/UltrafastEngine.Tests/bin/Release/net10.0/UltrafastEngine.Tests.dll NerTests Measured # filter: substring of Class.Method
dotnet tests/UltrafastEngine.Tests/bin/Release/net10.0/UltrafastEngine.Tests.dll --slow # all tests incl. slow (~5 min)
python3 python/tools/build_engine.py # after ANY C# or plugin-Python change, before Python tests
python3 python/tools/build_engine.py # after ANY C# or plugin-Python change, before Python tests (--plugins fitting: only those)
./setup.sh --cli --python --venv .venv --check # first-time source build for a user (build/setup.py --help; docs/install.md)
cd python && PYNLO_SRC=$PWD/third_party/pynlo/src ULTRAFAST_SLOW=1 python3 -m pytest -q tests # (get pyNLO: python3 tools/get_pynlo.py)
python3 -m mkdocs build --strict # docs: 0 warnings required
./build.sh --help # release packages (docs/releasing.md)
Expand All @@ -54,6 +55,7 @@ after a code change.

| task | start at |
|---|---|
| install / build for a user, which plugins | `docs/install.md`; `build/setup.py` (source), `install.py` (release), `build/package.py` (maintainer release) |
| how the engine works | `docs/concepts.md` (units, sign conventions, compile → execute, grids) |
| physics equations, solvers, NER | `docs/reference/nonlinear.md`; skill `engine-physics` |
| an option / element / instrument | `Schema/BuiltIn*.cs` (declaration) → `Engine/Compiler*.cs` (compile) → `Physics/` or `Instruments/` |
Expand Down
7 changes: 4 additions & 3 deletions PROJECT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
What is verified, where, and what is not checked yet. Capabilities and limits: [docs/capabilities.md](docs/capabilities.md).
What comes next: [ROADMAP.md](ROADMAP.md). Changes: [CHANGELOG.md](CHANGELOG.md).

## Verified (latest full run, macOS arm64, .NET 10, Python 3.12, 2026-11-10)
## Verified (latest full run, macOS arm64, .NET 10, Python 3.12, 2026-11-12)

| check | result |
|---|---|
| `dotnet build UltrafastEngine.sln -c Release` (net10.0 and net48) | 0 errors; the only warning is the expected missing ZOS-API (the Zemax binding then builds against stubs) |
| C# tests, `--slow` | **585 pass, 0 fail, 9 skipped** (8 `GpuTests` without a GPU device; the opt-in HAPI test) |
| Python tests (hosted engine, `ULTRAFAST_SLOW=1`, with pyNLO and LightPipes) | **251 pass, 2 skipped** (one needs `ULTRAFAST_NATIVE_LIB`; run 2026-11-11 with `ULTRAFAST_LIBRARY` set to the hosted engine, otherwise a stale `bin/native` shadows it and the plugin tests fail; includes the 23 release tests) |
| C# tests, `--slow` | **599 pass, 0 fail, 9 skipped** (8 `GpuTests` without a GPU device; the opt-in HAPI test) |
| Python tests (hosted engine, `ULTRAFAST_SLOW=1`, with pyNLO and LightPipes) | **260 pass, 2 skipped** (one needs `ULTRAFAST_NATIVE_LIB`; run 2026-11-11 with `ULTRAFAST_LIBRARY` set to the hosted engine, otherwise a stale `bin/native` shadows it and the plugin tests fail; includes the 23 release tests and 8 for `setup.py`, `install.py --preset` and the pulse calculator) |
| Component tests (`tests/components/run_all.py`: 10 families covering linear optics, splitters, polarisation, crystals, nonlinear media, spatial components, instruments) | **1691 / 1694 checks** pass against analytic answers; **3 are marked KNOWN** (a 1.5-cycle pulse broadened to zero frequency at 2 µm / 10 fs, reported by a warning), 0 fail |
| Paper replications (`build/paper_check.py`) | 12 folders, 0 hard failures (fast tier); each README ends with *How well the science matched*; the soft checks mark what does not reproduce ([index](docs/papers/README.md)) |
| Examples and tutorials (`build/example_check.py`, strict options) | 0 problems (60 example folders in 13 groups, 35 with a committed hero figure; the new AdaptiveOptics, DigitalTwin and Fibres examples checked on the last run); the C++ example and the OpticStudio export (`Interop/`) are manual |
| `mkdocs build --strict` | 0 warnings |
| Source-build front door (`build/setup.py`) | CLI with a plugin subset, Python into a fresh venv with `--check`, 2026-11-12 (macOS arm64). **Not run:** `--cpp` / `--python-engine native` (NativeAOT), Windows `setup.bat`, Linux; `release.yml` has never run on GitHub |
| Generated files (schemas, options.md, Python types, python-api.md, validation matrix) | current (checked by tests) |

## Continuous integration (GitHub Actions)
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@ focus is free-space optics, with single-mode fibres and gas cells where a system

```bash
git clone https://github.com/JosephCodemard/UltrafastEngine.git && cd UltrafastEngine
dotnet build UltrafastEngine.sln -c Release
dotnet run --project src/UltrafastEngine.Cli -c Release -- run docs/examples/GettingStarted/spm-plate/plate.ufs docs/examples/GettingStarted/spm-plate/run.json -o results
./setup.sh --cli --python --venv .venv --check # Windows: setup.bat. Needs the .NET 10 SDK and Python 3.10+
artifacts/cli/*/ultrafast run docs/examples/GettingStarted/spm-plate/plate.ufs docs/examples/GettingStarted/spm-plate/run.json -o results
```

No compiler? `python install.py --preset full` installs a release instead. Which command for which goal (CLI only, Python only,
some plugins, C API): [Install and build](docs/install.md).

```python
import ultrafast as uf
from ultrafast import build as b
Expand Down Expand Up @@ -162,7 +165,8 @@ The full documentation is at **<https://josephcodemard.github.io/UltrafastEngine

| | |
|---|---|
| [Getting started](docs/getting-started.md) | build on Windows, macOS (including Apple silicon) and Linux; Python setup |
| [Install and build](docs/install.md) | one table: release install, build from source, Python, C API, individual plugins |
| [Getting started](docs/getting-started.md) | repository layout, Visual Studio, first run |
| [Tutorials](docs/tutorials/index.md) | first run, diagnostics, a CPA chain, measured data, contrast, diffraction |
| [Examples](docs/examples/README.md) | 43 worked systems, from an SPM plate to a supercontinuum, regenerative amplifier, OPCPA, interferometers and instruments built from elements |
| [Reference](docs/reference/system-file.md) | system file, run spec, every element and instrument, models, results |
Expand Down
3 changes: 2 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Priorities, most useful first.
- [ ] Backward propagation through saturated gain and frequency conversion beyond linearisation
6. **Distribution and speed**
- [ ] Release workflow: a version tag builds the packages per platform, runs smoke tests and attaches them (and the Python wheels) to a GitHub release; the ZOS-API assemblies are never packaged
- [ ] Plugins as Python extras: `pip install "ultrafast[hitran,cuda,fitting]"`
- [x] One install story: `docs/install.md`, `build/setup.py` (source builds with plugin choice), `install.py --preset` (releases)
- [ ] Plugins as Python extras: `pip install "ultrafast[hitran,cuda,fitting]"`. The wheel and its extras are ready; **uploading to PyPI is not done and needs the owner's decision**
- [ ] GPU coverage: rotational Raman of gases, user responses as device kernels, χ(2), carrier-resolved propagation
- [ ] Mixed-precision (FP32) mode for the CUDA and OpenCL back-ends after a study of which steps tolerate it; Metal only if that study is favourable (Apple GPUs have no FP64)
- [ ] Speed: profile the hot paths (Hankel, Cartesian FFTs, instruments) and keep them allocation-free
Expand Down
Loading