Packing Systems into a Box¶
Fill a simulation cell with hundreds of molecules under geometric constraints —
from Python, through molpy's Packmol wrapper.
Prerequisites
Packmol is molpy's thin wrapper around the
Packmol executable: it writes the input
deck, shells out to packmol, and reads the result back into a Frame.
Install Packmol and put packmol on your PATH (or point at it explicitly:
Packmol(executable="/path/to/packmol")).
Prefer a pure-Python packer? Try molcrafts-molpack
molcrafts-molpack is our own
dependency-free, Python-native packer — a Rust Packmol port with collective
restraints and no external binary. pip install molcrafts-molpack; it
speaks the same molrs Frame, so it drops straight into the workflows below.
Give it a spin.
What packing solves¶
Building one molecule gives you one molecule. A simulation needs a box — often hundreds or thousands of molecules arranged without steric clashes. Doing that by hand (a grid, random insertion) either wastes volume or produces overlaps.
molpy's Packmol wrapper collects packing targets (a molecule + how many +
where it may go) and drives the Packmol executable to place them without clashes,
returning a single packed Frame.
Packing a box¶
from molpy.pack import Packmol, InsideBoxConstraint
p = Packmol(workdir="pack_out") # workdir for Packmol's scratch files
p.def_target(
water, # a molrs Frame (one molecule)
number=500, # how many copies
constraint=InsideBoxConstraint(length=30.0), # keep them inside a 30 Å cube
)
packed = p(max_steps=1000, seed=42) # -> a single packed Frame
Calling the packer — p(...) — runs Packmol and returns the packed Frame
directly. Register several def_targets before that call to pack a mixture
(e.g. solute + solvent) in one run.
The pieces¶
| Object | Role |
|---|---|
Packmol(executable=None, workdir=None) |
molpy's Packmol wrapper — the packing session. workdir holds Packmol's scratch files; executable points at a specific packmol binary. |
def_target(frame, number, constraint) |
Register number copies of frame, restricted by constraint. Returns the Target. |
packer(max_steps=1000, seed=None, pbc=None) |
Call the packer to run Packmol and return the packed Frame. pbc supplies a periodic cell for minimum-image spacing. |
Constraint catalog¶
A constraint restricts where a target's copies may be placed. Combine them with
AndConstraint / OrConstraint.
| Constraint | Keeps molecules… |
|---|---|
InsideBoxConstraint(length, origin=(0,0,0)) |
inside an axis-aligned cube of edge length at origin. |
OutsideBoxConstraint(origin, lengths) |
outside a box (carve out a cavity). |
InsideSphereConstraint(radius, center) |
inside a sphere. |
OutsideSphereConstraint(radius, center) |
outside a sphere. |
MinDistanceConstraint(dmin) |
at least dmin apart (clash avoidance). |
AndConstraint(a, b) / OrConstraint(a, b) |
satisfying both / either sub-constraint. |
from molpy.pack import InsideSphereConstraint, MinDistanceConstraint, AndConstraint
# inside a 20 Å sphere AND no closer than 2.5 Å to each other
c = AndConstraint(
InsideSphereConstraint(radius=20.0, center=(0.0, 0.0, 0.0)),
MinDistanceConstraint(dmin=2.5),
)
Parameters that matter¶
number— copies per target. Total atom count = Σ(number × atoms/molecule); this drives both memory and Packmol runtime.max_steps— Packmol's placement effort. Raise it for dense boxes that fail to converge; lower it for quick drafts.seed— reproducible packings. Pin it to get the same box twice.- box size vs
number— too many molecules for the volume makes Packmol struggle or fail; leave head-room, or pack in stages.
Pitfalls¶
packmolnot found → the run fails immediately. Install it / pass the path toPackmol(executable=...).- Over-dense boxes don't converge. If
optimizestalls, either enlarge the box constraint or reducenumber. - The returned object is a plain
Frame; attach a box / periodicity yourself if the downstream step needs one.
See also¶
- Building Polymers — producing the molecules you pack.
- Polydisperse Systems — packing a chain-length distribution.
- API Reference — Packing — full class/constraint reference.