rootstock 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rootstock-0.5.0/.github/workflows/publish.yml +30 -0
- rootstock-0.5.0/.gitignore +46 -0
- rootstock-0.5.0/CLAUDE.md +160 -0
- rootstock-0.5.0/LICENSE.md +7 -0
- rootstock-0.5.0/PKG-INFO +210 -0
- rootstock-0.5.0/README.md +190 -0
- rootstock-0.5.0/benchmarks/__init__.py +3 -0
- rootstock-0.5.0/benchmarks/direct.py +106 -0
- rootstock-0.5.0/benchmarks/sanity_check.py +241 -0
- rootstock-0.5.0/benchmarks/systems.py +77 -0
- rootstock-0.5.0/claude_docs/design-doc-v2.md +403 -0
- rootstock-0.5.0/claude_docs/design-doc-v3.md +535 -0
- rootstock-0.5.0/claude_docs/design-doc-v4.md +449 -0
- rootstock-0.5.0/claude_docs/design-doc-v5.md +475 -0
- rootstock-0.5.0/claude_docs/design-doc-v6.md +391 -0
- rootstock-0.5.0/claude_docs/design-doc-v7.md +188 -0
- rootstock-0.5.0/environments/chgnet_env.py +33 -0
- rootstock-0.5.0/environments/mace_env.py +36 -0
- rootstock-0.5.0/environments/tensornet_env.py +45 -0
- rootstock-0.5.0/environments/uma_env.py +40 -0
- rootstock-0.5.0/modal_app.py +527 -0
- rootstock-0.5.0/pyproject.toml +43 -0
- rootstock-0.5.0/rootstock/__init__.py +34 -0
- rootstock-0.5.0/rootstock/calculator.py +194 -0
- rootstock-0.5.0/rootstock/cli.py +426 -0
- rootstock-0.5.0/rootstock/clusters.py +41 -0
- rootstock-0.5.0/rootstock/environment.py +238 -0
- rootstock-0.5.0/rootstock/pep723.py +172 -0
- rootstock-0.5.0/rootstock/protocol.py +309 -0
- rootstock-0.5.0/rootstock/server.py +287 -0
- rootstock-0.5.0/rootstock/worker.py +273 -0
- rootstock-0.5.0/test_rootstock.sbatch +36 -0
- rootstock-0.5.0/uv.lock +3006 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
name: Build and publish to PyPI
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # Required for trusted publishing
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v4
|
|
25
|
+
|
|
26
|
+
- name: Build package
|
|
27
|
+
run: uv build
|
|
28
|
+
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
|
|
28
|
+
# IDE
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
|
|
34
|
+
# Modal
|
|
35
|
+
.modal/
|
|
36
|
+
|
|
37
|
+
# Benchmark outputs
|
|
38
|
+
results/
|
|
39
|
+
*.json
|
|
40
|
+
|
|
41
|
+
# OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
|
|
45
|
+
# Sockets (shouldn't be committed but just in case)
|
|
46
|
+
/tmp/ipi_*
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Rootstock is a proof-of-concept for running MLIP (Machine Learning Interatomic Potential) calculators in isolated pre-built Python environments, communicating via the i-PI protocol over Unix sockets.
|
|
8
|
+
|
|
9
|
+
**Current version: v0.5** - Pre-built environments with UMA and TensorNet support.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
### Running on Modal
|
|
14
|
+
```bash
|
|
15
|
+
# Initialize volume and build environments (takes ~10-15 min)
|
|
16
|
+
modal run modal_app.py::init_rootstock_volume
|
|
17
|
+
|
|
18
|
+
# Test pre-built environments
|
|
19
|
+
modal run modal_app.py::test_prebuilt
|
|
20
|
+
|
|
21
|
+
# Show status
|
|
22
|
+
modal run modal_app.py::inspect_status
|
|
23
|
+
|
|
24
|
+
# Run benchmarks
|
|
25
|
+
modal run modal_app.py::benchmark_v4
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Local Development
|
|
29
|
+
```bash
|
|
30
|
+
uv venv && source .venv/bin/activate
|
|
31
|
+
uv pip install -e ".[dev]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### CLI Commands
|
|
35
|
+
```bash
|
|
36
|
+
# Build a pre-built environment
|
|
37
|
+
rootstock build <env_name> --root <path> [--models m1,m2] [--force]
|
|
38
|
+
|
|
39
|
+
# Show status
|
|
40
|
+
rootstock status --root <path>
|
|
41
|
+
|
|
42
|
+
# List environments
|
|
43
|
+
rootstock list --root <path>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Linting
|
|
47
|
+
```bash
|
|
48
|
+
ruff check rootstock/
|
|
49
|
+
ruff format rootstock/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Architecture
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Main Process Worker Process (subprocess)
|
|
56
|
+
┌─────────────────────────┐ ┌─────────────────────────────┐
|
|
57
|
+
│ RootstockCalculator │ │ Pre-built venv Python │
|
|
58
|
+
│ (ASE-compatible) │ │ (mace_env/bin/python) │
|
|
59
|
+
│ │ │ │
|
|
60
|
+
│ server.py (i-PI server) │◄────────►│ worker.py (i-PI client) │
|
|
61
|
+
│ - sends positions │ Unix │ - receives positions │
|
|
62
|
+
│ - receives forces │ socket │ - calculates forces │
|
|
63
|
+
└─────────────────────────┘ └─────────────────────────────┘
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Key design**: v0.4 uses pre-built virtual environments instead of dynamic `uv run`. This provides:
|
|
67
|
+
- Fast startup (no pip install at runtime)
|
|
68
|
+
- Works on any filesystem (no lock files or hardlinks needed)
|
|
69
|
+
- Reproducible environments
|
|
70
|
+
|
|
71
|
+
### Core Files
|
|
72
|
+
|
|
73
|
+
- `rootstock/cli.py` - CLI commands (`build`, `status`, `list`, `register`)
|
|
74
|
+
- `rootstock/calculator.py` - ASE Calculator interface (main entry point)
|
|
75
|
+
- `rootstock/server.py` - Spawns worker subprocess, manages socket lifecycle
|
|
76
|
+
- `rootstock/worker.py` - i-PI client state machine
|
|
77
|
+
- `rootstock/environment.py` - Pre-built environment management, wrapper generation
|
|
78
|
+
- `rootstock/clusters.py` - Cluster registry and known environments
|
|
79
|
+
|
|
80
|
+
### Directory Structure
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
{root}/
|
|
84
|
+
├── .python/ # uv-managed Python interpreters (portable)
|
|
85
|
+
│ └── cpython-3.10.19-linux-x86_64-gnu/
|
|
86
|
+
├── environments/ # Environment SOURCE files (*.py with PEP 723)
|
|
87
|
+
│ ├── mace_env.py
|
|
88
|
+
│ ├── chgnet_env.py
|
|
89
|
+
│ ├── uma_env.py
|
|
90
|
+
│ └── tensornet_env.py
|
|
91
|
+
├── envs/ # Pre-built virtual environments
|
|
92
|
+
│ ├── mace_env/
|
|
93
|
+
│ │ ├── bin/python # Symlinks to .python/
|
|
94
|
+
│ │ ├── lib/python3.11/site-packages/
|
|
95
|
+
│ │ └── env_source.py # Copy of source for imports
|
|
96
|
+
│ └── chgnet_env/
|
|
97
|
+
└── cache/ # XDG_CACHE_HOME for model weights
|
|
98
|
+
├── mace/
|
|
99
|
+
└── huggingface/
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The entire `{root}/` directory is self-contained and portable. Python interpreters
|
|
103
|
+
are stored in `.python/` so venv symlinks resolve correctly on any machine where
|
|
104
|
+
the root directory is mounted (Modal Volume, HPC shared filesystem, etc.).
|
|
105
|
+
|
|
106
|
+
### Known Clusters
|
|
107
|
+
|
|
108
|
+
| Cluster | Root Path |
|
|
109
|
+
|---------|-----------|
|
|
110
|
+
| `modal` | `/vol/rootstock` |
|
|
111
|
+
| `della` | `/scratch/gpfs/SHARED/rootstock` |
|
|
112
|
+
|
|
113
|
+
## API
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
# v0.5 API: explicit model and checkpoint parameters
|
|
117
|
+
with RootstockCalculator(
|
|
118
|
+
cluster="della",
|
|
119
|
+
model="mace", # Environment family -> mace_env
|
|
120
|
+
checkpoint="medium", # Specific checkpoint (optional, uses default if omitted)
|
|
121
|
+
device="cuda",
|
|
122
|
+
) as calc:
|
|
123
|
+
atoms.calc = calc
|
|
124
|
+
energy = atoms.get_potential_energy()
|
|
125
|
+
|
|
126
|
+
# Checkpoint defaults to environment's default if omitted
|
|
127
|
+
with RootstockCalculator(cluster="della", model="uma") as calc:
|
|
128
|
+
... # Uses uma-s-1p1 by default
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Available Models
|
|
132
|
+
|
|
133
|
+
| Model | Environment | Default Checkpoint | Other Checkpoints |
|
|
134
|
+
|-------|-------------|-------------------|-------------------|
|
|
135
|
+
| `mace` | mace_env | `medium` | `small`, `large` |
|
|
136
|
+
| `chgnet` | chgnet_env | (pretrained) | — |
|
|
137
|
+
| `uma` | uma_env | `uma-s-1p1` | — |
|
|
138
|
+
| `tensornet` | tensornet_env | `TensorNet-MatPES-PBE-v2025.1-PES` | Other MatGL models |
|
|
139
|
+
|
|
140
|
+
## Build Process
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# 1. Create environment source file
|
|
144
|
+
cat > environments/mace_env.py << 'EOF'
|
|
145
|
+
# /// script
|
|
146
|
+
# requires-python = ">=3.10"
|
|
147
|
+
# dependencies = ["mace-torch>=0.3.0", "ase>=3.22", "torch>=2.0"]
|
|
148
|
+
# ///
|
|
149
|
+
|
|
150
|
+
def setup(model: str, device: str = "cuda"):
|
|
151
|
+
from mace.calculators import mace_mp
|
|
152
|
+
return mace_mp(model=model, device=device, default_dtype="float32")
|
|
153
|
+
EOF
|
|
154
|
+
|
|
155
|
+
# 2. Build pre-built environment
|
|
156
|
+
rootstock build mace_env --root /path/to/rootstock --models small,medium
|
|
157
|
+
|
|
158
|
+
# 3. Verify
|
|
159
|
+
rootstock status --root /path/to/rootstock
|
|
160
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2026 The University of Chicago
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
rootstock-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rootstock
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: MLIP calculators with isolated Python environments
|
|
5
|
+
License-File: LICENSE.md
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: ase>=3.22
|
|
8
|
+
Requires-Dist: numpy>=1.24
|
|
9
|
+
Requires-Dist: packaging>=21.0
|
|
10
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
14
|
+
Provides-Extra: mace
|
|
15
|
+
Requires-Dist: mace-torch>=0.3; extra == 'mace'
|
|
16
|
+
Requires-Dist: torch>=2.0; extra == 'mace'
|
|
17
|
+
Provides-Extra: modal
|
|
18
|
+
Requires-Dist: modal>=0.56; extra == 'modal'
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Rootstock
|
|
22
|
+
|
|
23
|
+
Run MLIP (Machine Learning Interatomic Potential) calculators in isolated pre-built Python environments, communicating via the i-PI protocol over Unix sockets.
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from ase.build import bulk
|
|
29
|
+
from rootstock import RootstockCalculator
|
|
30
|
+
|
|
31
|
+
atoms = bulk("Cu", "fcc", a=3.6) * (5, 5, 5)
|
|
32
|
+
|
|
33
|
+
# Using a known cluster
|
|
34
|
+
with RootstockCalculator(
|
|
35
|
+
cluster="modal", # or "della"
|
|
36
|
+
model="mace-medium", # or "chgnet", "mace-small", etc.
|
|
37
|
+
device="cuda",
|
|
38
|
+
) as calc:
|
|
39
|
+
atoms.calc = calc
|
|
40
|
+
print(atoms.get_potential_energy())
|
|
41
|
+
print(atoms.get_forces())
|
|
42
|
+
|
|
43
|
+
# Or with an explicit root path
|
|
44
|
+
with RootstockCalculator(
|
|
45
|
+
root="/scratch/gpfs/SHARED/rootstock",
|
|
46
|
+
model="mace-medium",
|
|
47
|
+
device="cuda",
|
|
48
|
+
) as calc:
|
|
49
|
+
atoms.calc = calc
|
|
50
|
+
print(atoms.get_potential_energy())
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Note:** Environments must be pre-built before use. See [Administrator Setup](#administrator-setup).
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install rootstock
|
|
59
|
+
# or
|
|
60
|
+
uv pip install rootstock
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Model String Format
|
|
64
|
+
|
|
65
|
+
The `model` parameter encodes both the environment and model-specific argument:
|
|
66
|
+
|
|
67
|
+
| `model=` | Environment | Model Arg |
|
|
68
|
+
|---------------------|----------------|---------------------|
|
|
69
|
+
| `"mace-medium"` | mace_env | `"medium"` |
|
|
70
|
+
| `"mace-small"` | mace_env | `"small"` |
|
|
71
|
+
| `"mace-large"` | mace_env | `"large"` |
|
|
72
|
+
| `"chgnet"` | chgnet_env | `""` (default) |
|
|
73
|
+
| `"mace-/path/to/weights.pt"` | mace_env | `"/path/to/weights.pt"` |
|
|
74
|
+
|
|
75
|
+
## Known Clusters
|
|
76
|
+
|
|
77
|
+
| Cluster | Root Path |
|
|
78
|
+
|---------|-----------|
|
|
79
|
+
| `modal` | `/vol/rootstock` |
|
|
80
|
+
| `della` | `/scratch/gpfs/SHARED/rootstock` |
|
|
81
|
+
|
|
82
|
+
For other clusters, use `root="/path/to/rootstock"` directly.
|
|
83
|
+
|
|
84
|
+
## Administrator Setup
|
|
85
|
+
|
|
86
|
+
Environments must be pre-built before users can run calculations.
|
|
87
|
+
|
|
88
|
+
### 1. Create Directory Structure
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
mkdir -p /scratch/gpfs/SHARED/rootstock/{environments,envs,cache}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Create Environment Source Files
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# mace_env.py
|
|
98
|
+
cat > /scratch/gpfs/SHARED/rootstock/environments/mace_env.py << 'EOF'
|
|
99
|
+
# /// script
|
|
100
|
+
# requires-python = ">=3.10"
|
|
101
|
+
# dependencies = ["mace-torch>=0.3.0", "ase>=3.22", "torch>=2.0"]
|
|
102
|
+
# ///
|
|
103
|
+
"""MACE environment for Rootstock."""
|
|
104
|
+
|
|
105
|
+
def setup(model: str, device: str = "cuda"):
|
|
106
|
+
from mace.calculators import mace_mp
|
|
107
|
+
return mace_mp(model=model, device=device, default_dtype="float32")
|
|
108
|
+
EOF
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 3. Build Environments
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Build MACE environment with model pre-download
|
|
115
|
+
rootstock build mace_env --root /scratch/gpfs/SHARED/rootstock --models small,medium,large
|
|
116
|
+
|
|
117
|
+
# Build CHGNet environment
|
|
118
|
+
rootstock build chgnet_env --root /scratch/gpfs/SHARED/rootstock
|
|
119
|
+
|
|
120
|
+
# Verify
|
|
121
|
+
rootstock status --root /scratch/gpfs/SHARED/rootstock
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Architecture
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Main Process Worker Process (subprocess)
|
|
128
|
+
+-------------------------+ +-----------------------------+
|
|
129
|
+
| RootstockCalculator | | Pre-built venv Python |
|
|
130
|
+
| (ASE-compatible) | | (mace_env/bin/python) |
|
|
131
|
+
| | | |
|
|
132
|
+
| server.py (i-PI server) |<-------->| worker.py (i-PI client) |
|
|
133
|
+
| - sends positions | Unix | - receives positions |
|
|
134
|
+
| - receives forces | socket | - calculates forces |
|
|
135
|
+
+-------------------------+ +-----------------------------+
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The worker process uses a pre-built virtual environment, providing:
|
|
139
|
+
- **Fast startup**: No dependency installation at runtime
|
|
140
|
+
- **Filesystem compatibility**: Works on NFS, Lustre, GPFS, Modal volumes
|
|
141
|
+
- **Reproducibility**: Same environment every time
|
|
142
|
+
|
|
143
|
+
## Directory Structure
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
{root}/
|
|
147
|
+
├── environments/ # Environment SOURCE files (*.py with PEP 723)
|
|
148
|
+
│ ├── mace_env.py
|
|
149
|
+
│ └── chgnet_env.py
|
|
150
|
+
├── envs/ # Pre-built virtual environments
|
|
151
|
+
│ ├── mace_env/
|
|
152
|
+
│ │ ├── bin/python
|
|
153
|
+
│ │ ├── lib/python3.11/site-packages/
|
|
154
|
+
│ │ └── env_source.py # Copy of environment source
|
|
155
|
+
│ └── chgnet_env/
|
|
156
|
+
└── cache/ # XDG_CACHE_HOME for model weights
|
|
157
|
+
├── mace/ # MACE models
|
|
158
|
+
└── huggingface/ # HuggingFace models
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## CLI Commands
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Build a pre-built environment
|
|
165
|
+
rootstock build <env_name> --root <path> [--models m1,m2] [--force]
|
|
166
|
+
|
|
167
|
+
# Show status
|
|
168
|
+
rootstock status --root <path>
|
|
169
|
+
|
|
170
|
+
# Register an environment source file
|
|
171
|
+
rootstock register <env_file> --root <path>
|
|
172
|
+
|
|
173
|
+
# List environments
|
|
174
|
+
rootstock list --root <path>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Running on Modal
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Initialize volume and build environments (takes ~10-15 min)
|
|
181
|
+
modal run modal_app.py::init_rootstock_volume
|
|
182
|
+
|
|
183
|
+
# Test pre-built environments
|
|
184
|
+
modal run modal_app.py::test_prebuilt
|
|
185
|
+
|
|
186
|
+
# Show status
|
|
187
|
+
modal run modal_app.py::inspect_status
|
|
188
|
+
|
|
189
|
+
# Run benchmarks
|
|
190
|
+
modal run modal_app.py::benchmark_v4
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Performance
|
|
194
|
+
|
|
195
|
+
IPC overhead is <5% for systems with 1000+ atoms compared to direct in-process execution.
|
|
196
|
+
|
|
197
|
+
| System Size | Atoms | Typical Overhead |
|
|
198
|
+
|-------------|-------|------------------|
|
|
199
|
+
| Small | 64 | ~10-15% |
|
|
200
|
+
| Medium | 256 | ~5-8% |
|
|
201
|
+
| Large | 1000 | <5% |
|
|
202
|
+
|
|
203
|
+
## Local Development
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
uv venv && source .venv/bin/activate
|
|
207
|
+
uv pip install -e ".[dev]"
|
|
208
|
+
ruff check rootstock/
|
|
209
|
+
ruff format rootstock/
|
|
210
|
+
```
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Rootstock
|
|
2
|
+
|
|
3
|
+
Run MLIP (Machine Learning Interatomic Potential) calculators in isolated pre-built Python environments, communicating via the i-PI protocol over Unix sockets.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from ase.build import bulk
|
|
9
|
+
from rootstock import RootstockCalculator
|
|
10
|
+
|
|
11
|
+
atoms = bulk("Cu", "fcc", a=3.6) * (5, 5, 5)
|
|
12
|
+
|
|
13
|
+
# Using a known cluster
|
|
14
|
+
with RootstockCalculator(
|
|
15
|
+
cluster="modal", # or "della"
|
|
16
|
+
model="mace-medium", # or "chgnet", "mace-small", etc.
|
|
17
|
+
device="cuda",
|
|
18
|
+
) as calc:
|
|
19
|
+
atoms.calc = calc
|
|
20
|
+
print(atoms.get_potential_energy())
|
|
21
|
+
print(atoms.get_forces())
|
|
22
|
+
|
|
23
|
+
# Or with an explicit root path
|
|
24
|
+
with RootstockCalculator(
|
|
25
|
+
root="/scratch/gpfs/SHARED/rootstock",
|
|
26
|
+
model="mace-medium",
|
|
27
|
+
device="cuda",
|
|
28
|
+
) as calc:
|
|
29
|
+
atoms.calc = calc
|
|
30
|
+
print(atoms.get_potential_energy())
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Note:** Environments must be pre-built before use. See [Administrator Setup](#administrator-setup).
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install rootstock
|
|
39
|
+
# or
|
|
40
|
+
uv pip install rootstock
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Model String Format
|
|
44
|
+
|
|
45
|
+
The `model` parameter encodes both the environment and model-specific argument:
|
|
46
|
+
|
|
47
|
+
| `model=` | Environment | Model Arg |
|
|
48
|
+
|---------------------|----------------|---------------------|
|
|
49
|
+
| `"mace-medium"` | mace_env | `"medium"` |
|
|
50
|
+
| `"mace-small"` | mace_env | `"small"` |
|
|
51
|
+
| `"mace-large"` | mace_env | `"large"` |
|
|
52
|
+
| `"chgnet"` | chgnet_env | `""` (default) |
|
|
53
|
+
| `"mace-/path/to/weights.pt"` | mace_env | `"/path/to/weights.pt"` |
|
|
54
|
+
|
|
55
|
+
## Known Clusters
|
|
56
|
+
|
|
57
|
+
| Cluster | Root Path |
|
|
58
|
+
|---------|-----------|
|
|
59
|
+
| `modal` | `/vol/rootstock` |
|
|
60
|
+
| `della` | `/scratch/gpfs/SHARED/rootstock` |
|
|
61
|
+
|
|
62
|
+
For other clusters, use `root="/path/to/rootstock"` directly.
|
|
63
|
+
|
|
64
|
+
## Administrator Setup
|
|
65
|
+
|
|
66
|
+
Environments must be pre-built before users can run calculations.
|
|
67
|
+
|
|
68
|
+
### 1. Create Directory Structure
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
mkdir -p /scratch/gpfs/SHARED/rootstock/{environments,envs,cache}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2. Create Environment Source Files
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# mace_env.py
|
|
78
|
+
cat > /scratch/gpfs/SHARED/rootstock/environments/mace_env.py << 'EOF'
|
|
79
|
+
# /// script
|
|
80
|
+
# requires-python = ">=3.10"
|
|
81
|
+
# dependencies = ["mace-torch>=0.3.0", "ase>=3.22", "torch>=2.0"]
|
|
82
|
+
# ///
|
|
83
|
+
"""MACE environment for Rootstock."""
|
|
84
|
+
|
|
85
|
+
def setup(model: str, device: str = "cuda"):
|
|
86
|
+
from mace.calculators import mace_mp
|
|
87
|
+
return mace_mp(model=model, device=device, default_dtype="float32")
|
|
88
|
+
EOF
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 3. Build Environments
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Build MACE environment with model pre-download
|
|
95
|
+
rootstock build mace_env --root /scratch/gpfs/SHARED/rootstock --models small,medium,large
|
|
96
|
+
|
|
97
|
+
# Build CHGNet environment
|
|
98
|
+
rootstock build chgnet_env --root /scratch/gpfs/SHARED/rootstock
|
|
99
|
+
|
|
100
|
+
# Verify
|
|
101
|
+
rootstock status --root /scratch/gpfs/SHARED/rootstock
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Architecture
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Main Process Worker Process (subprocess)
|
|
108
|
+
+-------------------------+ +-----------------------------+
|
|
109
|
+
| RootstockCalculator | | Pre-built venv Python |
|
|
110
|
+
| (ASE-compatible) | | (mace_env/bin/python) |
|
|
111
|
+
| | | |
|
|
112
|
+
| server.py (i-PI server) |<-------->| worker.py (i-PI client) |
|
|
113
|
+
| - sends positions | Unix | - receives positions |
|
|
114
|
+
| - receives forces | socket | - calculates forces |
|
|
115
|
+
+-------------------------+ +-----------------------------+
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The worker process uses a pre-built virtual environment, providing:
|
|
119
|
+
- **Fast startup**: No dependency installation at runtime
|
|
120
|
+
- **Filesystem compatibility**: Works on NFS, Lustre, GPFS, Modal volumes
|
|
121
|
+
- **Reproducibility**: Same environment every time
|
|
122
|
+
|
|
123
|
+
## Directory Structure
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
{root}/
|
|
127
|
+
├── environments/ # Environment SOURCE files (*.py with PEP 723)
|
|
128
|
+
│ ├── mace_env.py
|
|
129
|
+
│ └── chgnet_env.py
|
|
130
|
+
├── envs/ # Pre-built virtual environments
|
|
131
|
+
│ ├── mace_env/
|
|
132
|
+
│ │ ├── bin/python
|
|
133
|
+
│ │ ├── lib/python3.11/site-packages/
|
|
134
|
+
│ │ └── env_source.py # Copy of environment source
|
|
135
|
+
│ └── chgnet_env/
|
|
136
|
+
└── cache/ # XDG_CACHE_HOME for model weights
|
|
137
|
+
├── mace/ # MACE models
|
|
138
|
+
└── huggingface/ # HuggingFace models
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## CLI Commands
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Build a pre-built environment
|
|
145
|
+
rootstock build <env_name> --root <path> [--models m1,m2] [--force]
|
|
146
|
+
|
|
147
|
+
# Show status
|
|
148
|
+
rootstock status --root <path>
|
|
149
|
+
|
|
150
|
+
# Register an environment source file
|
|
151
|
+
rootstock register <env_file> --root <path>
|
|
152
|
+
|
|
153
|
+
# List environments
|
|
154
|
+
rootstock list --root <path>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Running on Modal
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Initialize volume and build environments (takes ~10-15 min)
|
|
161
|
+
modal run modal_app.py::init_rootstock_volume
|
|
162
|
+
|
|
163
|
+
# Test pre-built environments
|
|
164
|
+
modal run modal_app.py::test_prebuilt
|
|
165
|
+
|
|
166
|
+
# Show status
|
|
167
|
+
modal run modal_app.py::inspect_status
|
|
168
|
+
|
|
169
|
+
# Run benchmarks
|
|
170
|
+
modal run modal_app.py::benchmark_v4
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Performance
|
|
174
|
+
|
|
175
|
+
IPC overhead is <5% for systems with 1000+ atoms compared to direct in-process execution.
|
|
176
|
+
|
|
177
|
+
| System Size | Atoms | Typical Overhead |
|
|
178
|
+
|-------------|-------|------------------|
|
|
179
|
+
| Small | 64 | ~10-15% |
|
|
180
|
+
| Medium | 256 | ~5-8% |
|
|
181
|
+
| Large | 1000 | <5% |
|
|
182
|
+
|
|
183
|
+
## Local Development
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
uv venv && source .venv/bin/activate
|
|
187
|
+
uv pip install -e ".[dev]"
|
|
188
|
+
ruff check rootstock/
|
|
189
|
+
ruff format rootstock/
|
|
190
|
+
```
|