Skip to main content
Before you can simulate anything, you need atoms arranged in a box. warp-pack is a CPU-first packing engine that speaks Packmol’s language but runs in pure Rust.
warp-pack is a Packmol-compatible packing engine with JSON/YAML configs, bundled water templates, and restart file support.

Quick Start

# From JSON config
warp-pack --config pack.json --output packed.pdb --format pdb

# Packmol-style inputs also work
warp-pack --config packmol.inp

JSON Configuration

pack.json
{
  "box": { "size": [40.0, 40.0, 40.0], "shape": "orthorhombic" },
  "seed": 0,
  "min_distance": 2.0,
  "add_box_sides": true,
  "writeout": 30.0,
  "writebad": true,
  "restart_to": "packed.restart",
  "relax_steps": 10,
  "relax_step": 0.5,
  "output": { "path": "packed.pdb", "format": "pdb" },
  "structures": [
    {
      "path": "water.pdb",
      "count": 200,
      "rotate": true,
      "constraints": [
        { 
          "mode": "inside", 
          "shape": "sphere", 
          "center": [20.0, 20.0, 20.0], 
          "radius": 18.0 
        }
      ]
    },
    {
      "path": "ethanol.mol2",
      "count": 20,
      "filetype": "mol2",
      "changechains": true
    }
  ]
}

Bundled Water Templates

warp-pack ships with single-molecule water templates - no hunting for PDB files:
from warp_md.pack import water_pdb, Structure, PackConfig, Box
from warp_md.pack.runner import run

cfg = PackConfig(
    structures=[Structure(water_pdb("tip3p"), count=1000)],
    box=Box((40.0, 40.0, 40.0)),
    min_distance=2.0,
)
result = run(cfg)
Bundled water_pdb(...) templates are single-molecule PDBs. Perfect for packing, not for direct simulation.
Available models:
from warp_md.pack import available_water_models
print(available_water_models())  # ['tip3p', 'tip4p', 'spc', 'spce', ...]

Restart Files

Resume packing or reuse placements with Packmol-style restart files:
{
  "restart_from": "all.restart",
  "restart_to": "all.out.restart",
  "structures": [
    {
      "path": "water.pdb",
      "count": 200,
      "restart_from": "water.restart"
    }
  ]
}
Format: One line per molecule with six floats: x y z beta gamma theta

Supported Formats

Input Formats

  • pdb
  • xyz
  • mol2
  • pdbx / cif / mmcif
  • gro
  • lammps / lammps-data / lmp
  • crd
  • tinker / txyz
  • amber / inpcrd / rst / rst7

Output Formats

  • pdb (CONECT, TER, CRYST1)
  • xyz
  • pdbx / cif / mmcif
  • gro
  • lammps / lammps-data / lmp
  • mol2
  • crd

Configuration Reference

OptionWhat It Does
boxBox dimensions and shape
seedRandom seed for reproducibility
min_distanceHard minimum distance between atoms
writeoutWrite periodic snapshots (seconds)
writebadWrite partial structure on failure
restart_from / restart_toPackmol restart files
relax_steps / relax_stepPost-pack overlap relaxation
add_box_sidesAdd box dimensions to outputs
pbc_min / pbc_maxExplicit PBC bounds
OptionWhat It Does
pathPath to structure file
countNumber of copies to place
rotateAllow random rotation
filetypeOverride file type detection
constraintsPlacement constraints
radius / fscalePer-atom radius defaults
changechainsAssign unique chain IDs
rot_boundsConstrain Euler rotation ranges
fixed_eulersFix orientation (with positions)
// Inside a sphere
{ "mode": "inside", "shape": "sphere", "center": [20, 20, 20], "radius": 18 }

// Outside a box
{ "mode": "outside", "shape": "box", "min": [0, 0, 0], "max": [10, 10, 10] }

// Fixed position
{ "mode": "fixed", "position": [20, 20, 20] }

// Inside cylinder
{ "mode": "inside", "shape": "cylinder", "base": [0,0,0], "axis": [0,0,1], "radius": 10, "height": 20 }

// Inside ellipsoid
{ "mode": "inside", "shape": "ellipsoid", "center": [20,20,20], "radii": [10,10,15] }

Example: Solvated Protein

from warp_md.pack import Box, Structure, PackConfig, water_pdb
from warp_md.pack.runner import run
from warp_md.pack.export import export

cfg = PackConfig(
    structures=[
        # Protein at center (fixed)
        Structure("protein.pdb", count=1, constraints=[
            {"mode": "fixed", "position": [25.0, 25.0, 25.0]}
        ]),
        # Water molecules around protein
        Structure(water_pdb("tip3p"), count=5000, constraints=[
            {"mode": "outside", "shape": "sphere", "center": [25, 25, 25], "radius": 15}
        ]),
    ],
    box=Box((50.0, 50.0, 50.0)),
    min_distance=2.5,
    add_box_sides=True,
)

result = run(cfg)
export(result, "pdb", "solvated_protein.pdb")
print(f"Packed {result.total_atoms} atoms in {result.total_molecules} molecules")

Fluent Builder API

Chainable, readable packing configurations:
from warp_md.pack import PackConfigBuilder, water_pdb
from warp_md.pack.runner import run
from warp_md.pack.export import export

cfg = (
    PackConfigBuilder()
    .box(50.0, 50.0, 50.0)
    .seed(42)
    .min_distance(2.5)
    .add("protein.pdb", count=1)
        .fixed()
        .done()
    .add(water_pdb("tip3p"), count=5000)
        .outside_sphere([25, 25, 25], radius=15)
        .done()
    .add_box_sides(True)
    .build()
)

result = run(cfg)
export(result, "pdb", "solvated.pdb")

Integration with Peptide Builder

Pack a peptide structure generated by warp-pep:
import subprocess
from warp_md.pack import Box, Structure, PackConfig, water_pdb
from warp_md.pack.runner import run
from warp_md.pack.export import export

# Step 1: Build peptide
subprocess.run([
    "warp-pep", "build", 
    "-s", "ACDEFGHIKLMNPQRSTVWY",
    "--preset", "alpha-helix",
    "--oxt",
    "-o", "peptide.pdb"
], check=True)

# Step 2: Pack with water
cfg = PackConfig(
    structures=[
        Structure("peptide.pdb", count=1),
        Structure(water_pdb("tip3p"), count=1000),
    ],
    box=Box((40.0, 40.0, 40.0)),
    min_distance=2.0,
)

result = run(cfg)
export(result, "pdb", "solvated.pdb")
See Peptide Builder Guide for full peptide construction workflows.

Streaming Progress

Real-time progress tracking for agent integration:
warp-pack --config pack.json --stream
Emits NDJSON events to stderr:
{"event":"pack_started","total_molecules":150,"box_size":[50,50,50]}
{"event":"molecule_placed","molecule_index":10,"total_molecules":150,"progress_pct":6.7}
{"event":"gencan_iteration","iteration":100,"obj_value":2.1e-3,"progress_pct":10.0}
{"event":"pack_complete","total_atoms":4500,"elapsed_ms":52000}
See Streaming Progress API for full integration guide.

See Also

Build docs developers (and LLMs) love