API Reference
This page documents the public API of JAX-AMG.
Solver
jaxamg.solve(A, b, x0=None, config=None, block_dim=1, comm=None, nglobal=None, partition_info=None, save_stats_file=None, reuse_setup=False, nullspace=None, transpose_nullspace=None, **kwargs)
Solve Ax=b using the AmgX backend. See Examples for usage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A
|
MatrixOrOperator
|
Matrix or callable operator A(x). All matrices/operators are converted to |
required |
b
|
ArrayLike
|
Right-hand-side vector. In MPI mode this is the local RHS partition. |
required |
x0
|
ArrayLike | None
|
Optional initial guess (same shape as |
None
|
config
|
dict | None
|
AmgX configuration dictionary (see Solver Configuration for details). If |
None
|
block_dim
|
int
|
Treat the matrix as a block matrix with square |
1
|
comm
|
Comm | None
|
MPI communicator (typically |
None
|
nglobal
|
int | None
|
Global matrix row count for MPI mode. Required when |
None
|
partition_info
|
tuple[int, int] | None
|
|
None
|
save_stats_file
|
str | PathLike | None
|
Optional file path to save detailed AmgX solver statistics. If None, no file is created. |
None
|
reuse_setup
|
bool
|
For repeated solves with the same sparsity pattern, skip warm |
False
|
nullspace
|
NullSpaceSpec
|
Basis of |
None
|
transpose_nullspace
|
NullSpaceSpec
|
Basis of |
None
|
**kwargs
|
Any
|
Additional AmgX config parameters. These override values in |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
x |
Array
|
Solution vector (float32 or float64). In MPI mode, returns local portion. |
info |
dict
|
Dictionary containing |
Warns:
| Type | Description |
|---|---|
NullSpaceWarning
|
|
Status Codes
jaxamg.AMGXStatus
Bases: IntEnum
High-level AmgX solve status codes returned in info["status"] after calling jaxamg.solve.
These values are mapped from the native backend status for quick checks in Python code and in docs.
Members
SUCCESS: Solve converged successfully.FAILED: Solver failed due to an internal/runtime error.DIVERGED: Iterations diverged.NOT_CONVERGED: Reached stopping criteria without convergence.
JAX Sharding
jaxamg.ShardedMatrix
Distributed CSR matrix created by :func:make_sharded_matrix.
local_matrix(data=None)
Return this rank's unpadded BCSR matrix for data or cached values.
This is an eager helper: it reads the addressable shard of the packed
values (typically to unpack a computed matrix gradient), so it cannot
be applied to traced values inside jax.jit or another JAX
transformation.
jaxamg.ShardedSolve
Callable sharded solver created by :func:make_sharded_solver.
__call__(b, x0=None, *, A=None, save_stats_file=None)
Solve with the cached values or an explicit A.
A is this rank's (n_local, n_global) operator or matrix with the
sparsity fixed at solver creation, as solve(A, b) takes it, or the
packed global values in the layout of ShardedMatrix.data. Operator
parameters must be identical on every rank and receive the gradient of
the global loss; packed values receive their per-entry gradient. A
is required inside a JAX transformation. save_stats_file writes
AmgX statistics after a direct call (rank 0 writes the file; requires
save_stats=True at creation).
local_vector(value)
Return this rank's unpadded rows of a solver vector.
This is an eager helper: it reads the vector's addressable shard, so
it cannot be applied to traced values inside jax.jit or another
JAX transformation.
jaxamg.make_sharded_matrix(A_local, b, *, comm=None, mesh=None, axis_name='rank')
Create a distributed CSR container without replicating the global matrix.
The CSR column indices and row pointers remain rank-local static structure.
Matrix values are packed into a global JAX array sharded over the same mesh
axis as b. Unequal local nonzero counts are padded to the largest count;
the padding is ignored by solves and gradients.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A_local
|
MatrixOrOperator
|
This process's CSR row partition with shape
|
required |
b
|
Array
|
Global row-sharded RHS used to validate the matrix partition, mesh, and numerical dtype. |
required |
comm
|
Comm | None
|
MPI communicator spanning every JAX process, with rank order
matching the JAX process order. Defaults to |
None
|
mesh
|
Mesh | None
|
One-dimensional JAX device mesh. If omitted, use the mesh from
|
None
|
axis_name
|
str
|
Name of the mesh axis that partitions rows and packed values. |
'rank'
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
ShardedMatrix
|
class: |
ShardedMatrix
|
sharded values. The original global matrix is never materialized. |
jaxamg.make_sharded_vector(local_values, *, comm=None, mesh=None, global_size=None, axis_name='rank')
Create a row-sharded vector, padding unequal partitions.
The returned JAX array has equal physical shard sizes, as required by
NamedSharding. make_sharded_solver ignores each shard's padding and
uses the true row counts from A_local. JAX array inputs are padded and
assembled on device; other array-like inputs use a NumPy host staging path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
local_values
|
Any
|
This rank's unpadded values with shape |
required |
comm
|
Comm | None
|
MPI communicator spanning every JAX process, with rank order
matching |
None
|
mesh
|
Mesh | None
|
One-dimensional JAX device mesh with one device per MPI rank.
Defaults to a mesh over the first |
None
|
global_size
|
int | None
|
Optional true global length. When provided, it is checked against the sum of local lengths. |
None
|
axis_name
|
str
|
Mesh axis used to partition the vector. |
'rank'
|
Returns:
| Type | Description |
|---|---|
Array
|
A global JAX array whose axis uses |
Array
|
length is |
Array
|
|
jaxamg.make_sharded_solver(A, b, *, config=None, is_symmetric=False, block_dim=1, reuse_setup=False, save_stats=False)
Create a solver for a globally sharded RHS.
Whether the solve is compiled is entirely the caller's choice: this function
adds no jax.jit of its own. A caller that wraps its own function in
jax.jit gets the whole pipeline compiled as part of that single program
(through jax.shard_map). A direct, untransformed call instead executes
the rank-local pipeline on this process's shard -- the same code path as
solve(..., comm=...), with mpi4jax for the gradient exchanges -- and
reassembles global arrays, so it matches the MPI interface's eager speed.
This interface complements, rather than replaces, solve(..., comm=...).
JAX manages the global input and output arrays through shard_map while
the AmgX solve itself uses the supplied MPI communicator. The interface is
experimental; it uses a one-dimensional mesh and requires one MPI process
with one mesh-local GPU per rank and a communicator spanning every JAX
process.
jax.distributed.initialize() must be called before this function in a
multi-process job. The matrix owns the communicator, mesh, local CSR
structure, and globally sharded packed values. Pass A.data through
solver(..., A=A.data) to differentiate matrix values. Use
jax.set_mesh(A.mesh) around outer transforms such as jax.grad.
.. note::
Importing jaxamg disables XLA's cross-process sharded autotuning,
which deadlocks on the per-process programs a sharded solve compiles
to. Import it before the first JAX device call; see :doc:sharding.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A
|
ShardedMatrix
|
Distributed matrix created with :func: |
required |
b
|
Array
|
Global row-sharded JAX vector. Construct it with
:func: |
required |
config
|
dict[str, Any] | None
|
AmgX configuration. Defaults to the JAX-AMG MPI configuration. |
None
|
is_symmetric
|
bool
|
Whether the global matrix is symmetric. When |
False
|
block_dim
|
int
|
AmgX block dimension. The matrix retains its scalar CSR representation, and every local row partition must be divisible by this value. |
1
|
reuse_setup
|
bool
|
Reuse the cached AmgX hierarchy across solves with the same sparsity pattern. |
False
|
save_stats
|
bool
|
Prepare the AmgX configuration with solver-statistics
output enabled so a later direct call with
|
False
|
Returns:
| Type | Description |
|---|---|
ShardedSolve
|
A callable |
ShardedSolve
|
|
ShardedSolve
|
(its closed-over parameters must be identical on every rank) or the |
ShardedSolve
|
packed global values |
ShardedSolve
|
but is required under a JAX transform. |
ShardedSolve
|
unpacks a packed matrix gradient and |
ShardedSolve
|
removes vector padding. Info values have one entry per rank. |
Warnings
jaxamg.NullSpaceWarning
Bases: UserWarning
Null-space issue in jaxamg.solve: a singular matrix without a declared
nullspace, a missing nullspace/transpose_nullspace, a basis that is
not a null space, or a DENSE_LU_SOLVER coarse solve on a singular system.
Caching
jaxamg.with_cache(A, *, coloring=None, mpi=None, is_symmetric=False, nullspace=None, transpose_nullspace=None)
Attach cached metadata (coloring, MPI info, symmetry, null spaces) to a matrix or operator.
This cache allows using matrices/operators inside JIT-compiled functions without recomputing metadata or passing it as separate arguments. See Caching Guide for more details.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A
|
MatrixOrOperator
|
A matrix or operator. |
required |
coloring
|
tuple[ndarray, ndarray, ndarray, int, tuple[int, int]] | None
|
Cached coloring information from |
None
|
mpi
|
dict[str, Any] | None
|
Cached MPI metadata from |
None
|
is_symmetric
|
bool
|
If True, indicates the matrix is symmetric, allowing optimizations like skipping transpose in backward pass. |
False
|
nullspace
|
ArrayLike | str | None
|
Default for |
None
|
transpose_nullspace
|
ArrayLike | str | None
|
Default for |
None
|
Returns:
| Type | Description |
|---|---|
MatrixOrOperator
|
The same matrix/operator with requested cache attached. |
jaxamg.cache_coloring(operator, shape)
Compute and cache coloring information for a callable operator.
Detection uses two methods, so the result is correct for ANY operator:
- Tracing: interpret the operator's jaxpr to recover the EXACT sparsity in a single trace (no probing), then colour and materialise it. Works for any JAX-expressed operator; skipped for operators that can't be traced structurally (opaque calls, data-dependent indexing).
- Probing (
probe_sparsity_pattern+get_column_coloring): exhaustive one-hot basis-vector probing, correct for any operator -- the fallback when tracing is unavailable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operator
|
Any
|
A callable operator A(x) that returns |
required |
shape
|
tuple[int, int] | int
|
Shape of the operator (n, m) or int size (for an n×n matrix). For a
distributed operator this is the local block |
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray, ndarray, int, tuple[int, int]]
|
Cached coloring information for reattachment with |
jaxamg.cache_mpi_metadata(config, comm, nglobal, partition_info, A, is_symmetric=False, save_stats=False, block_dim=1, singular=False)
Pre-compute and cache MPI metadata for JIT-compatible solver usage.
The cached metadata can be reused across multiple JIT-compiled function calls with different matrices or operators (same structure).
Note
This function performs all non-traceable MPI operations outside the JIT boundary:
- Computes static MPI communication metadata (recvcounts, displs)
- Prepares MPI communicator pointer and local rank
- Prepares config string
- Computes max nnz across all ranks
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict
|
AmgX configuration dict or string |
required |
comm
|
Comm
|
MPI communicator (from mpi4py.MPI.COMM_WORLD) |
required |
nglobal
|
int
|
Global matrix size (total rows across all ranks) |
required |
partition_info
|
tuple[int, int]
|
tuple (row_start, row_end) indicating which rows this rank owns |
required |
A
|
MatrixOrOperator
|
Matrix or operator to compute max nnz for buffer sizing |
required |
is_symmetric
|
bool
|
If True, the backward pass never transposes, so the
transpose output size ( |
False
|
save_stats
|
bool
|
If True, prepare the config with solver statistics output
enabled, so a later |
False
|
block_dim
|
int
|
BSR block size for AmgX (see |
1
|
singular
|
bool
|
Use the singular-system AMG defaults (see
Solver Configuration). Implied when
null-space bases are already attached to |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dictionary containing MPI metadata. |
Note
The returned dictionary includes the following keys:
recvcounts_tuple: Tuple of row counts per rankcomm_ptr: MPI communicator pointerlrank: Local GPU ranknglobal: Global matrix sizeconfig_str: Prepared configuration stringmax_nnz: Maximum nnz across all ranksnnz_out: This rank's local nnz(A^T) for the transpose output, orNonewhenis_symmetricis Truehalo_plan: Backward-pass halo-exchange plan for the gradient w.r.t. A (fetches only referenced remote solution entries)transpose_plan: Fixed transpose structure and value routing for a nonsymmetric matrix, orNonewhenis_symmetricis Truerow_indices: Local CSR row index for every matrix nonzero
Preconditioner
jaxamg.make_preconditioner(A, config=None, *, comm=None, nglobal=None, partition_info=None, save_stats_file=None, return_info=False, **kwargs)
Create a callable approximate inverse for external Krylov solvers.
The returned callable can be passed directly as the M argument to
jax.scipy.sparse.linalg.cg(...) or jax.scipy.sparse.linalg.bicgstab(...).
By default the approximate inverse is a single AMG V-cycle (solver="AMG",
max_iters=1), so each application is one cheap AMG sweep. This is deliberately
different from jaxamg.solve, whose default is a full Krylov solve (PBICGSTAB)
preconditioned by AMG: here AMG is the preconditioner and the outer Krylov
method owns the iteration. Pass config/kwargs for a stronger inner
application (e.g. more sweeps, a W-cycle, or max_iters=2).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A
|
MatrixOrOperator
|
Matrix or callable operator to precondition. |
required |
config
|
dict[str, Any] | None
|
Optional AmgX configuration. If omitted, a single-cycle AMG approximate-inverse config is used. |
None
|
comm
|
Comm | None
|
Optional MPI communicator for distributed solves. If |
None
|
nglobal
|
int | None
|
Global matrix row count for MPI mode. |
None
|
partition_info
|
tuple[int, int] | None
|
Local row partition |
None
|
save_stats_file
|
str | None
|
Optional stats output path passed to |
None
|
return_info
|
bool
|
If |
False
|
**kwargs
|
Any
|
Additional solver config overrides. |
{}
|
Returns:
| Type | Description |
|---|---|
Callable
|
A callable representing an approximate inverse |
jaxamg.make_lineax_preconditioner(operator, config=None, *, tags=_INHERIT_TAGS, comm=None, nglobal=None, partition_info=None, save_stats_file=None, **kwargs)
Wrap a Lineax operator as an AMG preconditioner operator.
This is the operator->operator counterpart of make_preconditioner: it maps a
system operator A (a lineax.AbstractLinearOperator) to a preconditioner
operator M with M.mv(r) ≈ A⁻¹ r, ready to hand to a Lineax solver via
options={"preconditioner": M}. It folds the usual make_preconditioner
plus FunctionLinearOperator wiring into a single call.
The operator's matrix-free action (operator.mv) is handed to JAX-AMG, whose
sparsity detection assembles the explicit matrix AmgX needs (traced in one pass
when possible, probed otherwise). The pattern is detected and cached eagerly
here, since Lineax solvers apply the preconditioner under jax.jit where
on-the-fly detection is impossible. A MatrixLinearOperator is assembled
directly from its concrete matrix instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operator
|
AbstractLinearOperator
|
The system operator to precondition. |
required |
config
|
dict[str, Any] | None
|
Optional AmgX configuration (see |
None
|
tags
|
Any
|
Lineax tags for the returned preconditioner. By default the operator's
own tags are inherited ( |
_INHERIT_TAGS
|
comm
|
Comm | None
|
Optional MPI communicator for distributed solves. |
None
|
nglobal
|
int | None
|
Global matrix row count for MPI mode. |
None
|
partition_info
|
tuple[int, int] | None
|
Local row partition |
None
|
save_stats_file
|
str | None
|
Optional stats output path passed to |
None
|
**kwargs
|
Any
|
Additional solver config overrides forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
FunctionLinearOperator
|
A |
Runtime Utilities
jaxamg.get_solver_cache_info()
Inspect the internal C++ AmgX solver caches.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dictionary with cache size/capacity and entry summaries |
dict[str, Any]
|
for single-GPU and MPI caches, plus whether isolated mode |
dict[str, Any]
|
( |
jaxamg.clear_solver_cache()
Clear the internal C++ AmgX solver cache. This releases all cached AmgX resources (matrices, solvers, vectors).
jaxamg.finalize()
Manually finalize AmgX resources. This clears the cache and calls AMGX_finalize. Normally only needed to be called manually in MPI mode to avoid shutdown-time resource warnings.