This page is for people who want to change rfx itself: fix a bug, add a feature or improve the docs. If you want to use rfx, start with the Quick Start.
Set up
git clone https://github.com/bk-squared/rfx.gitcd rfxpip install -e '.[dev]'rfx needs Python 3.11 or newer and JAX and jaxlib 0.10.2 or newer.
The dev extra installs pytest,
pytest-xdist, ruff and the other development tools. Everything below runs
on a CPU. To test on an NVIDIA GPU, install the JAX build that matches your
CUDA stack first, then check that JAX sees the device:
python -c "import jax; print(jax.devices())"Run the tests
The default test selection skips tests marked slow, gpu, slow_physics
and docs_consistency, so a plain pytest runs the fast suite:
# The tests for the area you changed (fastest feedback)python -m pytest tests/unit/ports -q
# The whole fast suite, in parallelpython -m pytest tests -q -n auto
# One marked group on purpose, for example the slow tests of one filepython -m pytest -o addopts="" -m slow tests/oracle/test_skin_depth_oracle.py -qThe whole fast suite takes a while on a laptop. Iterate on the narrowest set that covers your change, then run the wider suite before you open the pull request.
Tests are grouped by kind:
| Directory | What it holds |
|---|---|
tests/unit/ | behaviour of one module, grouped by area (ports/, sparams/, boundaries/, …) |
tests/oracle/ | comparisons with closed-form answers |
tests/crossval/ | comparisons with frozen results from other solvers (mostly gpu/slow) |
tests/locks/ | regression locks that pin existing behaviour |
tests/contracts/ | repository rules: docs, manifests, CI configuration |
Run the required checks
scripts/ci/local.sh runs, in order, the short checks every pull request must
pass: ruff, docs hygiene, the changelog fragment, the data budget, the PR body,
workflow YAML and tests/contracts. It stops at the first failure.
bash scripts/ci/local.sh # all checks except the PR bodybash scripts/ci/local.sh /tmp/body.md # also check a PR body you wroteThe lint step on its own is bash scripts/ci/lint.sh, which runs ruff with the
project’s rule selection. The fast test suite is not part of local.sh; CI runs
it when a pull request touches code.
Add a changelog fragment
Do not edit CHANGELOG.md. Add one file per pull request under changelog.d/:
changelog.d/<number>.<type>.md<number> is your pull request number (or the issue number), and <type> is
one of added, breaking, changed, deprecated, fixed or removed. A
change under rfx/ must add a fragment; docs-only and test-only changes may.
The file holds a heading and a few bullets, at most 12 lines:
### Fixed — a lumped inductor no longer carries a spurious series resistance (#1245)
- What changed for the user, the number they now get, and what to change in their script, if anything.The heading uses an em dash and must include #<number>. Check your fragment
with:
python scripts/changelog/assemble.py --checkchangelog.d/README.md has the full format.
Code conventions
- Type hints and a docstring on every public function and class.
dataclass(frozen=True)for value objects such as shapes and configs.- JAX-friendly hot paths:
jnpinstead ofnp, no in-place mutation, andjax.lax.scanfor loops that must stay JIT-compatible. snake_casefor functions and variables,PascalCasefor classes,UPPER_CASEfor module constants.- A change that affects users updates the matching page under
docs/public/. A code block in a public page must run; check it withpython scripts/check_public_docs_blocks.py --only guide/<page>.
Add a feature
- Write a failing test first, in
tests/unit/<area>/test_<feature>.py. - Implement it in the right module under
rfx/. Export new public API fromrfx/__init__.py. - Prefer an error to a silent fallback. If a combination is not supported, raise with a message that says what to do instead.
- Show it is right, not only that it runs. For a physics change, compare
with a closed form (
tests/oracle/) or a trusted reference, and say how far the result moved. - Update the docs and add the changelog fragment.
A new geometry primitive lives in rfx/geometry/. It implements the Shape
protocol in rfx/geometry/csg.py: mask(grid) and
mask_on_coords(x, y, z) return a boolean occupancy, and bounding_box()
returns its extent. Test it with Simulation.add(), including zero-thickness
and single-cell cases.
Open a pull request
- Fork the repository and create a branch, for example
git checkout -b fix/lumped-inductor-loss. - Commit with a descriptive message. Prefixes such as
feat:,fix:,docs:,refactor:andtest:help. - Run
bash scripts/ci/local.shand the tests for your area. - Open the pull request against
main. The template asks for two lines:Lane:names the area that owns the change (one of the repository’slane:*labels), andReview:records who reviewed it. Describe what changed, why, and the evidence: the test you added and any number that moved. - If a check fails, fix it and push again.
Where things live
rfx/ __init__.py public API re-exports api/ Simulation, Result and the run / S-parameter entry points simulation.py compiled uniform-grid time loop runners/ uniform, non-uniform and multi-device runners core/ Yee update equations boundaries/ CPML, UPML, PEC and PMC handling sources/ waveforms, plane waves, waveguide and coaxial ports sparams/ S-parameter extraction for each port family geometry/ shapes, CAD mesh import, rasterization materials/ dispersive and thin-conductor models preflight/ the checks behind sim.preflight() farfield.py near-to-far-field transform rcs.py radar cross section optimize.py gradient-based inverse designtests/ the test suite (see above)examples/ the learning-path scriptsvalidation/ cross-solver comparison scriptsdocs/public/ the public documentation sourceQuestions
Open an issue on GitHub.
