Metadata-Version: 2.4
Name: dendra-solvers
Version: 0.5.1
Summary: Implicit cable and tree solvers with CPU and Apple Metal backends.
License-Expression: BSD-3-Clause
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: C++
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch>=2.12.0
Dynamic: license-file

# dendra-solvers

Differentiable implicit solvers for Dendra, with native C++ CPU kernels and
Metal kernels for Apple GPUs through PyTorch's MPS device.

## Installation

```bash
pip install dendra-solvers
```

Python 3.10+ and PyTorch 2.12+ are required. When a compatible wheel is
available, installation does not require a compiler. Stable-ABI wheels work
across supported Python and PyTorch versions on the same operating system and
CPU architecture.

For an HPC environment or custom PyTorch build, install PyTorch first and build
the extension against that installation:

```bash
python -m pip install "torch>=2.12.0" "setuptools>=77.0.3,<82" ninja wheel
MAX_JOBS=1 python -m pip install --no-build-isolation --no-cache-dir \
  --no-deps --no-binary=dendra-solvers dendra-solvers
```

The build uses the C++ standard selected by your installed PyTorch. Use a
C++20-capable compiler for current PyTorch releases. Stable-ABI builds do not
need rebuilding just because PyTorch is upgraded; see
[installation and clean rebuilds](docs/installation.md) for wheel availability,
source builds, and upgrading older installations.

Useful build options:

- `DENDRA_NATIVE=1` enables host-specific compiler optimizations. Do not use it
  for redistributable builds.
- `DENDRA_OMP=1` enables OpenMP when its runtime is available.
- `MAX_JOBS=1` limits compilation concurrency on memory-constrained systems.

## Devices and precision

The public solve functions select their backend from the numeric tensors'
device. General Thomas, PCR, 3×3 block-Thomas, scalar/block DHS trees and packed
multi-morphology DHS support CPU float32/float64 and MPS float32. The owning
DHS plan and physical-increment interfaces support the same devices.

MPS requires an available PyTorch MPS device and
[`torch.mps.compile_shader`](https://docs.pytorch.org/docs/stable/generated/torch.mps.compile_shader.html).
`dendra_solvers.is_mps_available()` checks both without compiling a shader.
Kernel compilation is lazy; CPU use does not initialize the Metal library.
Float64, float16/bfloat16 and the dedicated SPD/consuming APIs are currently
unsupported on MPS. CPU precision and SPD behavior are unchanged.

Keep immutable topology plans on CPU and place the numeric tensors on MPS:

```python
import torch
from dendra_solvers import DHSPlan, dhs_solve_plan, is_mps_available

if not is_mps_available():
    raise RuntimeError("An available PyTorch MPS device is required")

parent = torch.tensor([-1, 0, 0], dtype=torch.int64, device="cpu")
order = torch.tensor([1, 2, 0], dtype=torch.int64, device="cpu")
layers = torch.tensor([0, 2, 3], dtype=torch.int64, device="cpu")
plan = DHSPlan(parent, order, layers)

d_mem = torch.full(
    (2, 3), 2.0, device="mps", dtype=torch.float32, requires_grad=True
)
a_geom = torch.tensor(
    [[0.0, 0.2, 0.3]], device="mps", dtype=torch.float32
).expand_as(d_mem)
rhs = torch.ones_like(d_mem)
voltage = dhs_solve_plan(d_mem, a_geom, rhs, plan)
torch.testing.assert_close(voltage, torch.full_like(voltage, 0.5))
voltage.square().sum().backward()
torch.testing.assert_close(d_mem.grad, torch.full_like(d_mem, -0.25))
```

General solvers retain their reverse/forward AD, higher-order and `vmap`
interfaces on MPS. Numeric solves execute on the GPU; topology validation and
ownership remain on CPU. See [solver contracts](docs/solver-contracts.md) for
the supported APIs and [transform usage](docs/torch-func.md) for compilation.

## Testing

For a development checkout:

```bash
python -m pip install "torch>=2.12.0" "setuptools>=77.0.3,<82" ninja wheel numpy pytest
MAX_JOBS=1 python -m pip install -v --no-build-isolation --no-deps -e .
python -c "import dendra_solvers._ext as ext; print(ext.__file__)"
python -m pytest -q -ra
```

Solver contracts and PyTorch transform usage are documented in [`docs/`](docs/).

See [Contributing](CONTRIBUTING.md) for development tools, commit conventions,
and versioning.

## License

dendra-solvers is licensed under the [BSD 3-Clause License](LICENSE).
