Skip to main content

Rootstock

Rootstock lets you run many machine-learned interatomic potentials (MLIPs) on an HPC cluster from a single ASE-compatible calculator, without managing the conflicting Python environments each MLIP requires.

Each MLIP family runs in its own pre-built, isolated Python environment that a maintainer has already installed and verified on the cluster. Swapping models is a one-line change to the checkpoint argument, even when the MLIPs need different Python or library versions.

Full documentation: garden-ai.github.io/rootstock. See which models are supported on which clusters on the Matter Model Almanac.

Support

This work is supported by NSF Award #2514142: “Collaborative Research: Frameworks: SINAPSE: Scalable Infrastructure for AI-coupled Predictive Simulation Enhancement”

Availability

Rootstock is deployed on a growing set of HPC clusters. Which checkpoints are installed where lives in the Matter Model Almanac. If your cluster isn't supported but you want it to be, please reach out to Will Engler at willengler@uchicago.edu.

Quick Start

Rootstock is designed for use on an HPC cluster where models have been set up by a maintainer. The code below runs in a Python environment with rootstock and ASE installed. This could be inside a SLURM job script, an interactive session, a Jupyter notebook on the cluster, etc..

from ase.build import bulk
from rootstock import RootstockCalculator

atoms = bulk("Cu", "fcc", a=3.6) * (5, 5, 5)

with RootstockCalculator(
    cluster="delta",
    checkpoint="mace-mp-0-medium",
    device="cuda",
) as calc:
    atoms.calc = calc
    print(atoms.get_potential_energy())
    print(atoms.get_forces())

Swap the underlying potential by changing checkpoint, e.g. checkpoint="uma-s-1p1".

Installation

Users install only the lightweight rootstock package. The heavy ML dependencies (PyTorch, MACE, FAIRChem, etc.) live in the pre-built environments on the cluster.

pip install rootstock
# or
uv pip install rootstock

API

checkpoint is the canonical id of a specific set of trained weights (e.g. mace-mp-0-medium, uma-s-1p1). The hosting environment is resolved automatically — Rootstock walks the installed envs and finds the one whose CHECKPOINTS table declares the id.

# Pick a checkpoint by canonical id; env is resolved automatically.
RootstockCalculator(cluster="delta", checkpoint="mace-mp-0-medium")

# Forward extra kwargs to the env's setup() function:
RootstockCalculator(cluster="delta", checkpoint="uma-s-1p1", setup_kwargs={"task": "omol"})

# Custom root path instead of a known cluster
RootstockCalculator(root="/scratch/gpfs/specific/install/path/rootstock", checkpoint="mace-mp-0-medium")

Available Models

What is deployed and verified per cluster changes over time. The Matter Model Almanac and the Clusters page show the current coverage.

Architecture

When you create a RootstockCalculator, Rootstock spawns a subprocess that runs the MLIP in its own pre-built virtual environment. The main process and worker communicate over a Unix domain socket using the i-PI protocol. This happens on a single node (no remote network calls).

Your script (on cluster node)          Worker subprocess
+-------------------------+          +-----------------------------+
| RootstockCalculator     |          | Pre-built MLIP environment  |
| (ASE-compatible)        |          |                             |
|                         |          |                             |
| server.py (i-PI server) |<-------->| worker.py (i-PI client)     |
| - sends positions       |   Unix   | - receives positions        |
| - receives forces       |  socket  | - calculates forces         |
+-------------------------+          +-----------------------------+

This design takes out the pain of environment conflicts when experimenting with different MLIPs or using multiple MLIPs in a single workflow. The tradeoff is that it adds some overhead due to the inter-process communication, around 4% on an 864 atom system.

LAMMPS Support (Experimental)

Rootstock ships an experimental LAMMPS fix that spawns a worker subprocess, giving a LAMMPS run access to a Rootstock-managed MLIP for molecular dynamics. It is far less tested than the ASE path. See LAMMPS Integration in the docs for the fix syntax and current limitations.

Usage Statistics

On shared installs where the maintainer has provisioned it, each worker session drops one small anonymous JSON record into the install's {cache_root}/usage/ directory: which environment/checkpoint/device ran, when, for how long, how many force calls it served, and which entry point started it. Nothing phones home — records stay on the cluster's shared filesystem until the install's maintainer aggregates them (rootstock usage report). No job ids, no simulation data, and no raw usernames are recorded: the only per-person field is a salted hash used to count distinct users, and checkpoints you register yourself with rootstock add-local appear as (local), never by name.

If any of this rubs you the wrong way, opt out for all of your sessions with:

export ROOTSTOCK_DISABLE_USAGE_STATS=1

Maintainers opt an entire install out by not provisioning the spool (rootstock setup-perms --no-usage-spool) — if the directory doesn't exist, nothing is ever recorded.

Setting Up a New Cluster

This section is for people setting up Rootstock on a new cluster. All commands below are run on the cluster itself (SSH in first). You'll need write access to a shared filesystem location visible to your users.

1. Install Rootstock

On a login node:

pip install rootstock

2. Initialize the Rootstock directory

Choose a location on an appropriate shared filesystem where users can read but only maintainers can write. Then run:

rootstock init

This will interactively prompt you for:

  • root — the shared directory path (e.g., /scratch/shared/rootstock)
  • api_key / api_secret — optional credentials for pushing the cluster manifest to the Rootstock dashboard. Contact a Rootstock maintainer if you want your cluster to appear on the dashboard. These are Modal Proxy Auth Tokens.
  • maintainer name / email — identifies the maintainer for this installation

3. Install environments

Still on the login node — install only builds the venv:

# Install individual environments
rootstock install mace.py
rootstock install uma.py
rootstock install tensornet.py

# Or point it at a directory with multiple environments
rootstock install ./environments/

Each rootstock install command creates an isolated virtual environment under {root}/envs/ and installs the MLIP's dependencies. This can take several minutes per environment depending on the MLIP.

4. Add checkpoints

Use rootstock add to download model weights and verify them on the GPU. Download and verify can run on different nodes — useful when your GPU node has no network access:

# Login node (CPU, has network): download only
rootstock add mace-mp-0-medium --no-verify
rootstock add uma-s-1p1 --no-verify

# GPU node: skip download (already fetched), verify on GPU
rootstock add mace-mp-0-medium
rootstock add uma-s-1p1

# Forward extra kwargs to setup() — values are JSON-decoded, fall back to strings
rootstock add uma-s-1p1 --kwarg task=omat

rootstock add is idempotent. Use rootstock smoke-test to re-verify all fetched checkpoints (suitable for nightly cron with --json).

rootstock status shows a per-checkpoint grid of fetched/verified/stale state. See the dashboard for environment files that are known to work.

Users can also bring their own weights (e.g. a fine-tuned UMA model) without any write access to the shared install — rootstock add-local registers a local file under a checkpoint id that then works everywhere a canonical id does:

rootstock add-local /scratch/me/my-uma-ft.pt --env uma --id my-uma-ft --kwarg task=omol
rootstock remove-local my-uma-ft   # delete the registration (never the file)

The registration lives in the per-user registry (~/.config/rootstock/local-checkpoints.json); the hosting env must declare a setup_from_path() function (see docs/environments.md).

5. Register with the dashboard (optional)

If you configured API credentials during rootstock init, the manifest is pushed automatically when you install or update environments. If the push failed (e.g., due to network issues), you can retry:

rootstock manifest push

Directory Structure

After setup, the rootstock root directory will look like this:

{root}/
├── .python/                # uv-managed Python interpreters
├── environments/           # Environment source files (*.py with PEP 723 metadata)
│   ├── mace.py
│   ├── uma.py
│   └── tensornet.py
├── envs/                   # Pre-built virtual environments
│   ├── mace/
│   │   ├── bin/python
│   │   ├── lib/python3.11/site-packages/
│   │   └── env_source.py
│   └── ...
├── home/                   # Redirected HOME for not-well-behaved libraries
│   ├── .cache/fairchem/
│   └── .matgl/
└── cache/                  # XDG_CACHE_HOME and HF_HOME for well-behaved libraries
    ├── mace/
    └── huggingface/

The home/ directory exists because some ML libraries (FAIRChem, MatGL) ignore XDG_CACHE_HOME and write to ~/.cache/ unconditionally. Rootstock redirects HOME during builds and at worker runtime so that model weights end up in the shared directory rather than in individual users' home directories.

Writing Environment Files

Each MLIP is defined by a small Python file with PEP 723 inline metadata for its dependencies, a CHECKPOINTS table mapping canonical checkpoint ids to whatever string the upstream library expects, and a setup() function that dispatches via that table and returns an ASE calculator:

# /// script
# requires-python = ">=3.11"
# dependencies = ["mace-torch>=0.3.14", "ase>=3.22", "torch>=2.0,<2.10"]
# ///

CHECKPOINTS = {
    "mace-mp-0-small":  "small",
    "mace-mp-0-medium": "medium",
    "mace-mp-0-large":  "large",
}


def setup(checkpoint: str, device: str = "cuda"):
    from mace.calculators import mace_mp
    return mace_mp(model=CHECKPOINTS[checkpoint], device=device, default_dtype="float32")

CHECKPOINTS is the env's local dispatch table. The keys are the canonical ids that show up in rootstock add <id> and in RootstockCalculator(checkpoint=<id>); the values are whatever string the upstream library wants. A typo in the canonical id errors immediately ("no installed env declares ...") instead of failing inside setup().

Rootstock uses uv to build an isolated virtual environment from these dependencies. The setup() function is called once when a worker starts, and the returned calculator is reused for all subsequent calculations in that session.

Local Development

git clone https://github.com/Garden-AI/rootstock.git
cd rootstock
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
ruff check rootstock/
ruff format rootstock/

Get Involved

We welcome feedback, bug reports, and collaborators. If you're interested in deploying Rootstock on your cluster, contributing environment files for new MLIPs, or using it for a research project, contact Will Engler at willengler@uchicago.edu.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rootstock-1.1.0.tar.gz (1.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rootstock-1.1.0-py3-none-any.whl (128.0 kB view details)

Uploaded Python 3

File details

Details for the file rootstock-1.1.0.tar.gz.

File metadata

  • Download URL: rootstock-1.1.0.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for rootstock-1.1.0.tar.gz
Algorithm Hash digest
SHA256 25b24641e21b97d25b85d4c0084ed322dfc92cc4e1a9e13d3100d55fa07552ae
MD5 73c224dfbba5486de5162824c2a8a3d8
BLAKE2b-256 6c47fca69105afa58d10b6ffea72a91c930afc8601f58afc978ca5e738a988d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for rootstock-1.1.0.tar.gz:

Publisher: publish.yml on Garden-AI/rootstock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rootstock-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: rootstock-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 128.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for rootstock-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e17c115802a141b859f3c3a3aeb16cfad75d4eb9aa878adf4bfca271ba073a45
MD5 450925faa239a323fe7af752d9e18d10
BLAKE2b-256 e3cb73509231704a7ed2f5399232bbde3a63c1539fb2f4145f436b902d667f53

See more details on using hashes here.

Provenance

The following attestation bundles were made for rootstock-1.1.0-py3-none-any.whl:

Publisher: publish.yml on Garden-AI/rootstock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.6.4

2 files

1.6.3

2 files

1.6.2

2 files

1.6.1

2 files

1.6.0

2 files

1.5.0

2 files

1.4.3

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.0

2 files

1.2.0

2 files

This release

1.1.0 This release

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

0.9.8

2 files

0.9.7

2 files

0.9.6

2 files

0.9.5

2 files

0.9.4

2 files

0.9.3

2 files

0.9.2

2 files

0.9.1

2 files

0.9.0

2 files

0.8.1

2 files

0.8.0

2 files

0.7.3

2 files

0.7.1

2 files

0.7.0

2 files

0.6.1

2 files

0.5.1

2 files

0.5.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page