Features · Install · Example · Docs · Citation
jNO (jax Numerical Operators) is a JAX-native library for differentiable
numerical methods. Classical solvers — finite elements, finite differences,
and spectral (RCWA) — and scientific machine learning — PINNs, neural operators,
Bayesian inference — are two pillars on one substrate: you write the math
(a weak form, a strong-form stencil, a PDE residual, a data loss), and it lowers
to a single GPU-ready, end-to-end reverse-mode-differentiable, jit-compiled graph.
Because every solve is differentiable, the things that are usually separate frameworks are the same tool here: an inverse problem, a PDE-constrained optimization, and a neural-network coefficient are one composition away from a forward solve — no glue code, no finite differences, no leaving JAX.
[!NOTE] Research-level repository under active development. The public API is stabilising but may change between minor versions. Parts of the numerical-methods stack are marked experimental below — the scope and known limitations are stated on each docs page.
What you can do with jNO
Pillar 1 — Differentiable numerical methods
| Capability | Maturity | Notes |
|---|---|---|
FEM, nodal — jno.fem |
stable | Lagrange P1 / P2 / P3+, 2-D & 3-D; steady (linear + Newton), transient (θ-method), second-order-in-time (wave / elastodynamics), complex, periodic, coupled multifield |
| FEM, non-nodal — H(div) / H(curl) / C¹ | experimental | Raviart–Thomas (H(div)) and Nédélec edge (H(curl) — Maxwell, eddy currents) elements; C¹ Hermite / Argyris / Morley (plates, biharmonic) |
FDM — jno.fdm |
stable | Strong-form collocation from a term list; structured grids + geometric multigrid; unstructured meshes; periodic, coupled, flux BCs; 2-D & 3-D |
Spectral / RCWA — jno.rcwa |
stable | Vector-Maxwell RCWA, anisotropic media, Jones / polarization readout |
Linear & nonlinear solvers — jno.solve / jno.precond |
stable | Sparse-direct LU, Jacobi-BiCGStab, GMRES, CG, MINRES, Chebyshev, geometric multigrid, optional GPU AMG — matrix-free and differentiable |
Generalized eigenproblems — fem.eigs |
beta | K x = λ M x, differentiable, M-orthonormal |
| Time integration | stable | θ-method (backward-Euler / Crank–Nicolson), exponential integrators, adaptive step size |
Adaptive meshing — jno.solve.remesh / relocate, and coord.d(t) - v as a term |
beta | Hessian-metric remeshing (AFEM), r-adaptivity, moving meshes stated in the term list |
| Differentiable inverse / PDE-constrained | stable | Recover a scalar, a field k(x), the geometry, or a neural coefficient through any solve — the gradient flows through the whole march |
Geometry — jno.Shape / jno.Path |
stable | CSG via gmsh-OCC; conforming multi-material regions |
Pillar 2 — Scientific machine learning
| Capability | Maturity | Notes |
|---|---|---|
| Forward PINNs (residual minimisation) | stable | Hard or soft BC enforcement |
| Variational PINNs (weak-form losses) | stable | Network trial functions against the FEM weak form |
| Operator learning (DeepONet, FNO, U-Net, PROSE via foundax) | stable | PDE-residual or data-driven |
| Adaptive resampling (RAD, RARD, CR3, R3, pinnfluence) | stable | |
| Stochastic PDEs & noise nodes (gaussian / uniform / laplace) | stable | Fokker–Planck, stochastic forcing |
| Bayesian PINNs (NUTS, HMC, MALA, SGLD, SGHMC, VI) | stable | model.bayesian(kernel_factory) mirrors .optimizer() — per-parameter, mixed freely |
| Parameter-efficient fine-tuning (LoRA, DoRA, rsLoRA, PiSSA, VeRA, LoKr, OFT, IA3) | stable | Chain .lora(...) on any wrapped model |
| Training explainability (gradient conflict, NTK, Hessian, loss landscape, input sensitivity) | stable | |
| Foundation-model integration (foundax MLPs, transformers, DeepONet, FNO, PROSE) | stable | Wrap any Equinox module via jno.nn(...) |
| Hybrid data + model parallelism | stable | jno.core(..., mesh=(batch, model)) |
| W&B logging + Orbax checkpointing | stable | |
| IREE / MLIR compiled inference for deployment | stable |
One tracing language bridges the two. A weak form, a strong-form stencil, a PDE residual for a network, and a supervised loss all lower to the same differentiable, jit-compiled graph — so a classical solve, a PINN, and an inverse problem compose rather than living in separate stacks. 29 worked tutorials span elliptic, parabolic, hyperbolic, coupled, inverse, integral, stochastic, FEM / variational, Bayesian, and operator-learning problems — browse the tutorials index.
Install
pip install jax-numerical-operators
One install — FEM, FDM, the solver stack, PINNs, and the scientific-ML tooling all come in the box, running on CPU out of the box. An NVIDIA GPU is one extra away — pip install "jax-numerical-operators[cuda]" — and the heavy, self-contained backends stay behind extras too: [fem] (adaptive remeshing + the PARDISO/cuDSS sparse-direct backends), [rcwa] (the Fourier-modal EM solver), [amg] (GPU algebraic multigrid), [iree], combinable as [cuda,fem]. The Installation guide has the full table, plus Pixi, Docker, and pinning a specific CUDA build.
PS: I recommend pulling the latest main branch to always be up to date!
Example
Differentiable FEM & FDM — one term list, weak or strong form
import jno
d = jno.Shape.rect(0, 0, 1, 1, size=0.05).domain()
xi, yi, _ = d.variable("interior", split=True)
xb, yb, _ = d.variable("boundary", split=True)
# The same BVP two ways — −Δu = 1 on the unit square, u = 0 on the boundary.
# FEM — the WEAK form is the term list (with a test function v):
u, v = d.fem_symbols()
ui, vi = u.bind(x=xi, y=yi), v.bind(x=xi, y=yi)
u_fem = jno.fem([ui.x * vi.x + ui.y * vi.y - 1.0 * vi, # ∫∇u·∇v − ∫f·v = 0
u(xb, yb) - 0.0]).solve()
# FDM — the STRONG form: the same term list, no test function, collocated at the nodes:
w = d.unknown()
wi = w.bind(x=xi, y=yi)
u_fdm = jno.fdm([-wi.d2(xi) - wi.d2(yi) - 1.0, # −Δu = 1
w(xb, yb) - 0.0]).solve()
# Both are sparse, matrix-free, GPU-ready, and end-to-end differentiable —
# wrap either in an objective to recover a coefficient, a source, or the geometry.
RCWA — a periodic metasurface, from the same constraint list (click to expand)
import jno
import jax.numpy as jnp
# A periodic metasurface unit cell — a patterned high-index slab between two ambients.
K0 = 2 * jnp.pi # vacuum wavenumber (wavelength λ = 1)
d = jno.Shape.box(0, 0, 0, 0.6, 0.6, 1.0, size=0.12).domain()
d.tag("bottom", lambda x, y, z: z < 0.01); d.tag("top", lambda x, y, z: z > 0.99) # z ambients
d.tag("left", lambda x, y, z: x < 0.01); d.tag("right", lambda x, y, z: x > 0.59) # x-periodic
d.tag("front", lambda x, y, z: y < 0.01); d.tag("back", lambda x, y, z: y > 0.59) # y-periodic
u, v = d.fem_symbols()
xi, yi, zi, _ = d.variable("interior", split=True)
ui, vi = u.bind(x=xi, y=yi, z=zi), v.bind(x=xi, y=yi, z=zi)
def on(tag): # bind u, v on a named face
s = d.variable(tag, split=True)
return u.bind(x=s[0], y=s[1], z=s[2]), v.bind(x=s[0], y=s[1], z=s[2])
(ut, vt), (ub, vb) = on("top"), on("bottom")
ul, ur, uf, ubk = on("left")[0], on("right")[0], on("front")[0], on("back")[0]
slab = jno.fn(lambda x, y, z: jnp.where((0.4 < z) & (z < 0.6), 1.0, 0.0), [xi, yi, zi])
eps = 1.0 + 10.0 * slab # a patterned slab (swap in jno.np.parameter(...) for inverse design)
# the SAME scalar-Helmholtz list you'd hand jno.fem — rcwa infers period, layers, ε, and incidence:
sol = jno.rcwa([
ui.x * vi.x + ui.y * vi.y + ui.z * vi.z - K0**2 * eps * (u * vi), # ∇u·∇v − k₀²·ε·u·v
-(1j * K0 * ut) * vt, # outgoing radiation (top ambient)
-(1j * K0 * ub - 2j * K0) * vb, # incident plane wave + radiation (bottom)
ul - ur, uf - ubk, # Floquet periodicity (x and y)
], orders=200).solve()
sol.efficiency("T") # transmitted power fraction (needs the [rcwa] backend)
sol.order(+1, 0) # a chosen diffraction order
Operator learning — a DeepONet trained on a PDE residual (click to expand)
import jno
import jax
import optax
import foundax
dir = jno.setup("./runs/test")
# Domain: `500 *` batches 500 random-coefficient samples of the same geometry
dom = 500 * jno.Shape.rect(0, 0, 2, 1, size=0.05).domain()
x, y, _ = dom.variable("interior")
xb, yb, _ = dom.variable("boundary")
k = dom.variable("k", jax.random.uniform(jax.random.PRNGKey(0), shape=(500, 1, 1), minval=0.5, maxval=1.5))
# Network + optimizer
fx = foundax.deeponet(n_sensors=1, coord_dim=2, basis_functions=32, hidden_dim=128, activation=jax.numpy.tanh)
net = jno.nn(fx)
net.optimizer(optax.adam(optax.schedules.cosine_decay_schedule(1e-3, 20_000, alpha=1e-5)))
# Hard BC enforcement via an output transform; the PDE residual is the loss
u = net(k, jno.np.concat([x, y], axis=-1)) * x * (2 - x) * y * (1 - y)
pde = k * (u.dd(x) + u.dd(y)) + 1.0
crux = jno.core(constraints=[pde.mse], domain=dom)
crux.solve(epochs=20_000, batchsize=32).plot(f"{dir}/training.png")
jno.save(crux, f"{dir}/model.pkl")
Citation
If you use jNO in academic work, please cite:
@article{armbruster2026jno,
title = {jNO: A JAX Library for Neural Operator and Foundation Model Training},
author = {Armbruster, Leon and Ramesh, Rathan and Kruse, Georg and Straub, Christopher},
journal = {arXiv preprint arXiv:2605.10159},
year = {2026},
doi = {10.48550/arXiv.2605.10159},
url = {https://arxiv.org/abs/2605.10159}
}
AI Disclosure
Parts of this codebase — including model ports, tests, and documentation — were developed with the assistance of AI coding tools. All contributions are reviewed and tested to the best of our ability, but mistakes may remain; please open an issue if you spot one.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jax_numerical_operators-0.3.0.tar.gz.
File metadata
- Download URL: jax_numerical_operators-0.3.0.tar.gz
- Upload date:
- Size: 1.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
321842e111334b037145ad83fe36578f15b48bfeb6f8fe97c4dd4bd0de05978d
|
|
| MD5 |
dcae71671d98b81ad3ac06898440dd33
|
|
| BLAKE2b-256 |
5a5f0cf3392e6ffcd46721264398a37d94c9bdeaf8cb674448909832242b6d06
|
Provenance
The following attestation bundles were made for jax_numerical_operators-0.3.0.tar.gz:
Publisher:
publish-pypi.yml on FhG-IISB/jNO
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jax_numerical_operators-0.3.0.tar.gz -
Subject digest:
321842e111334b037145ad83fe36578f15b48bfeb6f8fe97c4dd4bd0de05978d - Sigstore transparency entry: 2422607623
- Sigstore integration time:
-
Permalink:
FhG-IISB/jNO@c0aa3c3dcf79bca474319f428879e69f8d931115 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/FhG-IISB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@c0aa3c3dcf79bca474319f428879e69f8d931115 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file jax_numerical_operators-0.3.0-py3-none-any.whl.
File metadata
- Download URL: jax_numerical_operators-0.3.0-py3-none-any.whl
- Upload date:
- Size: 1.2 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09378e8f6bc36e2dbea15f6e3483e0dce57ae88cd5ae14fc9af6b3ea0075eb0d
|
|
| MD5 |
86efbaf3a9e47f6759eacfab8eec5a88
|
|
| BLAKE2b-256 |
ca9b638865bc5604f51a70d84bdec21b4857331a746f086712420c97082c0b39
|
Provenance
The following attestation bundles were made for jax_numerical_operators-0.3.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on FhG-IISB/jNO
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jax_numerical_operators-0.3.0-py3-none-any.whl -
Subject digest:
09378e8f6bc36e2dbea15f6e3483e0dce57ae88cd5ae14fc9af6b3ea0075eb0d - Sigstore transparency entry: 2422607817
- Sigstore integration time:
-
Permalink:
FhG-IISB/jNO@c0aa3c3dcf79bca474319f428879e69f8d931115 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/FhG-IISB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@c0aa3c3dcf79bca474319f428879e69f8d931115 -
Trigger Event:
workflow_dispatch
-
Statement type: